"Render into an AppKit NSView using libmpv's render/client API."
Two Ways to Show the Video
An embedded engine has to draw somewhere. The lazy way is to let the engine open its own window and drive it — quick to start, and a dead end. That window isn't part of your app; your keyboard shortcuts don't reach it, your full-screen transitions fight it, your on-video overlays have nowhere to live. You end up with a remote control taped to a stranger's TV.
The right way is the one libmpv is designed for: its render API lets the engine draw into a surface you provide. Ashen Reel gives it an AppKit NSView, and the video renders inside the app's own window — inside the responder chain, under the overlays, part of the composition you control.
Why 'Inside Your Window' Changes Everything
Once the video lives in an NSView you own, a pile of hard features become nearly free. The seek overlay draws on top because it's a sibling view. Full screen and Spaces behave because it's a normal window. The keyboard chords reach it because it's in the responder chain. Double-click-to-fullscreen and scroll-to-change-volume work because the view receives the events. None of that is possible when the engine holds its own detached window.
The render API works on a callback: libmpv signals from its own thread that a new frame is ready, you hop to the main thread and mark the view for redraw, and AppKit asks you to present. Here's the shape, simplified:
The payoff is a player that feels native because it is native — the borrowed engine paints pixels into Ashen Reel's own glass, and every window, key, and overlay behaves like the AppKit app it actually is.