Skip to content

Feature request: native video playback (hs.ui video element or hs.video) #149

Description

@yosbeda

Background

I built a motivational-image overlay in HS2: on hotkey press, a photo pops up near a corner of the screen for a set number of seconds, then auto-hides. That works using hs.ui.window() + .image()/.resizable()/.aspectRatio(). I'm now trying to do the same thing with a short looping video instead of a static photo, and that's where it broke down.

(Heads up going in — I work through Swift source with AI help rather than reading it myself, so if I've mischaracterized anything below, that's why.)

Context

hs.ui has no AVPlayer/AVKit usage anywhere as far as I can tell, and HSUIWindow.image() only accepts HSImage — no video-capable overload.

What's still blocked

The only path I found to video is hs.ui.webview() + a hand-rolled HTML5 <video autoplay loop muted playsinline> tag. That works, but took two separate debugging sessions:

  1. No video element exists in hs.ui — has to go through a webview as a workaround.
  2. webview.loadHTML(htmlString) silently refuses to resolve a file:// resource referenced inside the HTML string — no error anywhere. Fix: write the HTML to a temp file and load it via loadURL("file://" + path) instead, which gives WebKit a real base URL.

Proposed API (rough sketch, not attached to this exact shape)

  • hs.ui.window().video(path) — mirrors .image(HSImage), or a standalone player.newFromFile(path) if that fits better
  • .loop(bool), .autoplay(bool), .muted(bool)
  • .resizable()/.aspectRatio() — reuse what .image() already has

Second gap, same overlay pattern: hs.ui.window has no native click-outside/resign-key dismiss — no way to just say "close when the user clicks elsewhere." Has to be hand-rolled with an hs.eventtap watcher that checks every click on screen against a manually tracked window frame. Something like window.dismissOnClickOutside(true) would remove that entirely.

Can test against a real file once there's something to try.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions