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

Feat/media UI extensions live et al #476

Merged

Conversation

cjpillsbury
Copy link
Collaborator

This adds support for APIs currently being drafted in media-ui-extensions, including:

Additionally, it updates the behavior of the media-live-button per prior conversations around presentation and behavior related to the media-paused state.

@cjpillsbury cjpillsbury requested review from a team and heff as code owners February 16, 2023 19:22
@vercel
Copy link

vercel bot commented Feb 16, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated
media-chrome ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Feb 24, 2023 at 9:09PM (UTC)
media-chrome-docs ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Feb 24, 2023 at 9:09PM (UTC)

@codecov
Copy link

codecov bot commented Feb 16, 2023

Codecov Report

Merging #476 (5ac376a) into main (c77cd43) will decrease coverage by 0.05%.
The diff coverage is 73.13%.

❗ Current head 5ac376a differs from pull request most recent head d5c757f. Consider uploading reports for the commit d5c757f to get more accurate results

@@            Coverage Diff             @@
##             main     #476      +/-   ##
==========================================
- Coverage   68.51%   68.47%   -0.05%     
==========================================
  Files          43       43              
  Lines        6797     6807      +10     
==========================================
+ Hits         4657     4661       +4     
- Misses       2140     2146       +6     
Impacted Files Coverage Δ
src/js/media-live-button.js 77.38% <42.85%> (-0.94%) ⬇️
src/js/media-controller.js 66.34% <76.27%> (-0.16%) ⬇️
src/js/constants.js 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

'emptied,durationchange,loadedmetadata,targetlivewindowchange': () => {
this.propagateMediaState(
MediaUIAttributes.MEDIA_TARGET_LIVE_WINDOW
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: On unchanged lines https://github.com/muxinc/media-chrome/pull/476/files#diff-f093c2ba0a65c5a566a4ad86659ffc5bee29bfbbc241f863bed8f634b7a0f9f7R508-R510 where we monitor for events to update MEDIA_TIME_IS_LIVE, this does not account for all cases where that value may change, nor is there any set of events on an HTMLMediaElement that would catch all cases. Given our current use case, we may want to instead model something like MEDIA_IS_PLAYING_LIVE that means:

  1. media is currently playing
  2. the media playing is within the live edge window

This more circumscribed attribute should be able to be reliably updated based on events and would simplify media-live-button.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not clear where these edge cases are, but I think the important thing is not that every change is captured, but that when it's needed by the UI, it's up to date. The existing version seems ok to me from that standpoint, at least as a starting point.

I don't love media-is-playing-live because we already have media-paused to tell half that story.

Copy link
Collaborator Author

@cjpillsbury cjpillsbury Feb 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the updated implementation of media-live-button in this PR, the edge case will not be a problem. However, the media-time-is-live will "lie" on a subset of initialization cases for live/dvr, particularly when autoplay is off. As long as we're ok with that attribute not always being accurate, we can definitely treat that as out of scope and a "we'll deal with it if/when it becomes an issue" scenario, since it doesn't impact any current media chrome use cases/components.

package.json Outdated Show resolved Hide resolved
// If there's no way to seek, assume the media element is keeping it "live"
if (streamIsLive && !seekable) {
return true;
if (typeof media.liveEdgeStart === 'number') {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this move into its own getter function for consistency?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, maybe. We can wait until we need it in two places.

const getStreamType = (controller) => {
const { media } = controller;

if (!media) return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, this returned null, why the change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for consistency with the spec. If there's no slotted media, I'm treating this as equivalent to "unimplemented". From "the out side" (aka the attribute value), this should be identical regardless.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting to look at this from either the media element or media chrome perspective. I could see this being "media chrome knows what stream type is, but it's unknown". But I'm good with matching the spec here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heff yup was mulling on the same thing and this is where I (soft) landed. Open to rethinking that moving forward for this kinda stuff if we wanted to discuss in one of our weekly meetings.

}

return false;
const liveEdgeStartOffset = controller.hasAttribute('livethreshold')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this attribute be with respect to the new proposal? Maybe to match the variable name?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree this attribute should get a rename. Since the proposal moved to liveEdgeStart, there isn't an explicit equivalent of livethreshold (it's effectively the variable name liveEdgeStartOffset). Do you think the attribute should be liveedgestartoffset? or liveedgeoffset (maybe a bit confusing, though that was the name of the property in the previous iteration of the proposal)? or something else? Def open to suggestions here (Names Are Hard™️)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

liveedgeease :)

liveedgeoffset sounds pretty good to me

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool I'll run with that unless folks have any concerns.

}
const live = getStreamType(controller) === 'live';
// Can't be playing live if it's not a live stream
if (!live) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (non-b): 1 empty line after a return statement might help reading the code

// always assume playing live
if (!seekable) return true;
// If there is an empty `seekable`, assume we are not playing live
if (!seekable.length) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -84,6 +84,7 @@ export const MediaUIAttributes = {
MEDIA_LOADING: 'media-loading',
MEDIA_BUFFERED: 'media-buffered',
MEDIA_STREAM_TYPE: 'media-stream-type',
MEDIA_TARGET_LIVE_WINDOW: 'media-target-live-window',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we'll change the name of this based on the conversation of Edge vs. Seekable window? Just a question, not a suggestion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe so. I think "target live window" makes sense still in our "DVR" proposal. We can always amend it if necessary once we move video-dev/media-ui-extensions#4 to an official proposal PR, since there isn't a custom/extended media element that supports this yet (and mux-video will be the first, so we can treat it as "internal")

'emptied,durationchange,loadedmetadata,targetlivewindowchange': () => {
this.propagateMediaState(
MediaUIAttributes.MEDIA_TARGET_LIVE_WINDOW
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not clear where these edge cases are, but I think the important thing is not that every change is captured, but that when it's needed by the UI, it's up to date. The existing version seems ok to me from that standpoint, at least as a starting point.

I don't love media-is-playing-live because we already have media-paused to tell half that story.

// If there's no way to seek, assume the media element is keeping it "live"
if (streamIsLive && !seekable) {
return true;
if (typeof media.liveEdgeStart === 'number') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, maybe. We can wait until we need it in two places.

}

return false;
const liveEdgeStartOffset = controller.hasAttribute('liveedgeoffset')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Name change. Might require a docs change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick search and didn't see any docs, but I'll be sure to do a more thorough audit before merging.

const getStreamType = (controller) => {
const { media } = controller;

if (!media) return undefined;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting to look at this from either the media element or media chrome perspective. I could see this being "media chrome knows what stream type is, but it's unknown". But I'm good with matching the spec here.

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.

4 participants