Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Picture-in-Picture support #22

Merged
merged 9 commits into from
Jan 16, 2025
Merged

Conversation

christriants
Copy link
Contributor

@christriants christriants commented Dec 14, 2024

This PR implements Picture-in-Picture support using the Document Picture-in-Picture API, and extension of the Picture-in-Picture API.

While this is an experimental technology, and browser-support is limited for now, I thought this would be cool to try out. Using the Picture-in-Picture API seems less optimal because it's only supported on the video element, but we are currently drawing our video to a canvas for playback. The Document Picture-in-Picture API makes it possible to open an always-on-top window that can be populated with arbitrary HTML content — for example a video with custom controls or a set of streams showing the participants of a video conference call.

The core logic to support this function exists in the Picture-in-Picture Button component. togglePictureInPicture handles calling documentPictureInPicture.requestWindow, which opens the Picture-in-Picture window for the current main browsing context. We then take our canvas and append it to the picture-in-picture window, and update its width/height to 100% to fit the window. We then add an event listener for pagehide, which handles re-appending the canvas to the player container when the PiP window is closed.

Other additions:

  • We added a store.ts file, which could potentially be used to share state in multiple places. Right now, we're sharing pipState between watch.tsx and PictureInPictureButton.tsx
  • We created a global.d.ts file, so we could add declare a global type for DocumentPictureInPicture
  • We added a slate in watch.tsx to display in place of the canvas when the video is in PiP mode
Screenshot 2024-12-15 at 4 27 17 PM

Follow-up items:

  • Add player controls to the PiP window

@christriants christriants force-pushed the pip branch 2 times, most recently from 9bb4d5b to b924280 Compare December 15, 2024 21:18
@christriants christriants marked this pull request as ready for review December 15, 2024 21:27
@christriants
Copy link
Contributor Author

Fixed merge conflicts.

I haven't moved controls to the picture-in-picture window yet, nor have I added play/pause/mute functionality to it. Let me know if it's OK to file these as issues, rather than tackle those here!

@christriants
Copy link
Contributor Author

I haven't moved controls to the picture-in-picture window yet, nor have I added play/pause/mute functionality to it. Let me know if it's OK to file these as issues, rather than tackle those here!

Added basic functionality to play/pause the video from the PiP window by clicking on the window itself. Ideally, we wouldn't have to pass in a prop to this component, and instead, we could just access player.play from state. Even better, we could just render our existing PlayButton in the window, which would be easier / cleaner without prop-drilling.

@englishm englishm merged commit 6d00c66 into englishm:main Jan 16, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants