Coder Social home page Coder Social logo

muxinc / media-chrome Goto Github PK

View Code? Open in Web Editor NEW
1.0K 24.0 51.0 68.35 MB

Custom elements (web components) for making audio and video player controls that look great in your website or app.

Home Page: https://media-chrome.org

License: MIT License

JavaScript 97.80% TypeScript 2.20%
video audio video-player audio-player web-components ui-components mux media-chrome

media-chrome's Introduction

NPM Version NPM Downloads jsDelivr hits (npm) npm bundle size slack

Your media player's dancing suit. 🕺

Fully customizable media player controls using web components (native custom elements).

  • Compatible with any javascript framework (React, Angular, Svelte, etc.)
  • Compatible with the <video> and <audio> elements and a lot of players (YouTube, HLS.js, and more)
  • Simple HTML to add/remove controls
  • Simple CSS to style the controls

From Mux and the creator of Video.js.

Documentation

Visit the official documentation for Media Chrome for the latest up-to-date usage instructions.

You can find the documentation for v0.x of media-chrome here.

Examples

See all of the repo examples in action.

Video Example

<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome@3/+esm"></script>

<media-controller>
  <video
    slot="media"
    src="https://stream.mux.com/DS00Spx1CV902MCtPj5WknGlR102V5HFkDe/high.mp4"
    crossorigin
  >
    <track
      label="thumbnails"
      default
      kind="metadata"
      src="https://image.mux.com/DS00Spx1CV902MCtPj5WknGlR102V5HFkDe/storyboard.vtt"
    />
  </video>
  <media-control-bar>
    <media-play-button></media-play-button>
    <media-mute-button></media-mute-button>
    <media-volume-range></media-volume-range>
    <media-time-range></media-time-range>
    <media-pip-button></media-pip-button>
    <media-fullscreen-button></media-fullscreen-button>
  </media-control-bar>
</media-controller>
Media Chrome Video Player Demo

Audio Example

<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome@3/+esm"></script>

<media-controller audio>
  <audio
    slot="media"
    src="https://stream.mux.com/O4h5z00885HEucNNa1rV02wZapcGp01FXXoJd35AHmGX7g/audio.m4a"
  ></audio>
  <media-control-bar>
    <media-play-button></media-play-button>
    <media-time-display showduration></media-time-display>
    <media-time-range></media-time-range>
    <media-playback-rate-button></media-playback-rate-button>
    <media-mute-button></media-mute-button>
    <media-volume-range></media-volume-range>
  </media-control-bar>
</media-controller>
Media Chrome Audio Player Demo

Use with React

While you technically can use Media Chrome elements directly with React, it can sometimes be a bit clunky to work with Web Components in React, and some things just don't feel idiomatic to the framework (for example: having to use class= instead of className=, see React's official docs regarding web components for more details). To help with this, we've published some React wrapper components for all of our core Elements. You can read up on using them here.

Why?

More often than not web designers and developers just use the default media player controls, even when creating a beautiful custom design theme. It's hard not to.

  • Web browsers have built-in media controls that can't easily be customized and look different in every browser.
  • Social sites like Youtube, Vimeo, and SoundCloud only let you customize small details of the player, like primary button color.
  • Media controls are complex and hard to build from scratch. Open source players like Video.js and JW Player help, but require you to learn proprietary JS APIs, and can be difficult to use with popular Javascript frameworks.

It should be easier... <media-chrome> is an attempt at solving that.

Why now?

Web components. @heff spoke about the potential of web components for video at Demuxed 2015, and again in 2020. They allow us to extend the browser's base HTML functionality, meaning we can now build media player controls as simple HTML tags that:

  • Can be used like any native HTML tag in HTML, Javascript, and CSS (unleash your designer)
  • Are compatible by default with Javascript frameworks (React, Angular, Svelte)
  • Can be used across players when using multiple in the same site, e.g Youtube & <video>. (Could even be used by players as their own built-in controls)

Core Concepts

media-chrome's People

Contributors

adamjaggard avatar cjpillsbury avatar davekiss avatar derikolsson avatar dylanjha avatar evoactivity avatar github-actions[bot] avatar gkatsev avatar harveyrandall avatar heff avatar hermanbilous avatar jakubslambor avatar jonabc avatar jorisre avatar k-g-a avatar littlespex avatar luwes avatar mashaal avatar mattiasbuelens avatar mmcc avatar redopop avatar snyk-bot avatar wietsehage avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

media-chrome's Issues

Feature Request: made the seek backward/forward time configurable

Please consider making the seek backward/forward time configurable, presumably through an attribute on the element such as in the following:

<media-seek-backward-button amount="10"></media-seek-backward-button>

The amount, 30 seconds, is currently hardcoded as a constant used in the line:

const detail = Math.max(currentTime + DEFAULT_SEEK_OFFSET, 0);

The small visible number in the control bar curved arrow would also need to update to reflect the new seek back amount.

fullscreen in vertical video

With a portrait oriented video (typical mobile source), the full screen crops to the top section of the video element only.

didn't work for me :/

After having to remove the "type": "module", line from package.json thanks to Gulp, then firing up lite-server, I could not get any of the example files to work but the "youtube-controls". Some didn't show any sign of a player at all, & this seems odd

image

Win10, Firefox & Chromium based browser.

Add default enabling/showing for captions button.

Issue corresponding to discussion #137
Current implementation should:

  • add an attribute to the captions button to automatically enable captions
  • treat going from "no captions" (/subtitles, if relevant) to "some captions" (and vice versa) as a reset case.

Efficiency of element attribute changes

Every time a setAttribute is called on a custom element the attributeChangedCallback is triggered.
https://codesandbox.io/s/strange-golick-c10fz?file=/src/index.js

Should this be gated in the code below if there was no actual change to the attribute value?
Or should it be handled in the affected custom element itself?

const setAttr = (child, attrName, attrValue) => {
if (attrValue == undefined) {
return child.removeAttribute(attrName);
}
if (typeof attrValue === 'boolean') {
if (attrValue) return child.setAttribute(attrName, '');
return child.removeAttribute(attrName);
}
if (Number.isNaN(attrValue)) {
return child.removeAttribute(attrName);
}
return child.setAttribute(attrName, attrValue);
};

cuetext URLS in vtt file is getting query params stripped away

For example, if a storyboard.vtt file (used in <track label="thumbnails" default kind="metadata">) looks like this, media-chrome is erroneously stripping away the query params.

WEBVTT

00:00:00.000 --> 00:00:00.990
https://image.mux.com/8z7mnkC43KqXTHhpGz9fePf1Hxe1tCUk/storyboard.jpg?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImpXMDBJN1lRT2dUajAwek9VV24wMWtpaHhtUVpvREhnOXRyIn0.eyJleHAiOjE2MjI2MDA2NDcsImF1ZCI6InMiLCJzdWIiOiI4ejdtbmtDNDNLcVhUSGhwR3o5ZmVQZjFIeGUxdENVayJ9.JxAa8w0fV_F2g8KKiow51TXiTdepwttzPcHhFn6W-DfvWeI1eb_790E3pXFXjOYK8tD-2rxjiBQ_krW5kRRU7PPNipPw7Ta73Bv9YqjHkG2_1R5-J-W_b5WKvz8f0-jYc4px_q4bQmOt-NszSdnUJstfEw31E0jvStgTyGGNvJxzbZTQHbhseBoG5Lgmpv1aO5cowNM3osqQ2cQcPxW7wtP6rSDQlSYhW05FSPztCKxgGOct-P3xpUW7BPBh1OXKWfMjL_L9Qo3VFQ6ho7Z0k-TziXJqWVlvgnw_xJgpx1-Z6Hq8Qy3b3lCueyn86W2B_8VB1U-D-7L49KaMwztYPg#xywh=0,0,284,160

00:00:00.990 --> 00:00:01.980
https://image.mux.com/8z7mnkC43KqXTHhpGz9fePf1Hxe1tCUk/storyboard.jpg?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImpXMDBJN1lRT2dUajAwek9VV24wMWtpaHhtUVpvREhnOXRyIn0.eyJleHAiOjE2MjI2MDA2NDcsImF1ZCI6InMiLCJzdWIiOiI4ejdtbmtDNDNLcVhUSGhwR3o5ZmVQZjFIeGUxdENVayJ9.JxAa8w0fV_F2g8KKiow51TXiTdepwttzPcHhFn6W-DfvWeI1eb_790E3pXFXjOYK8tD-2rxjiBQ_krW5kRRU7PPNipPw7Ta73Bv9YqjHkG2_1R5-J-W_b5WKvz8f0-jYc4px_q4bQmOt-NszSdnUJstfEw31E0jvStgTyGGNvJxzbZTQHbhseBoG5Lgmpv1aO5cowNM3osqQ2cQcPxW7wtP6rSDQlSYhW05FSPztCKxgGOct-P3xpUW7BPBh1OXKWfMjL_L9Qo3VFQ6ho7Z0k-TziXJqWVlvgnw_xJgpx1-Z6Hq8Qy3b3lCueyn86W2B_8VB1U-D-7L49KaMwztYPg#xywh=284,0,284,160

00:00:01.980 --> 00:00:02.970
https://image.mux.com/8z7mnkC43KqXTHhpGz9fePf1Hxe1tCUk/storyboard.jpg?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImpXMDBJN1lRT2dUajAwek9VV24wMWtpaHhtUVpvREhnOXRyIn0.eyJleHAiOjE2MjI2MDA2NDcsImF1ZCI6InMiLCJzdWIiOiI4ejdtbmtDNDNLcVhUSGhwR3o5ZmVQZjFIeGUxdENVayJ9.JxAa8w0fV_F2g8KKiow51TXiTdepwttzPcHhFn6W-DfvWeI1eb_790E3pXFXjOYK8tD-2rxjiBQ_krW5kRRU7PPNipPw7Ta73Bv9YqjHkG2_1R5-J-W_b5WKvz8f0-jYc4px_q4bQmOt-NszSdnUJstfEw31E0jvStgTyGGNvJxzbZTQHbhseBoG5Lgmpv1aO5cowNM3osqQ2cQcPxW7wtP6rSDQlSYhW05FSPztCKxgGOct-P3xpUW7BPBh1OXKWfMjL_L9Qo3VFQ6ho7Z0k-TziXJqWVlvgnw_xJgpx1-Z6Hq8Qy3b3lCueyn86W2B_8VB1U-D-7L49KaMwztYPg#xywh=568,0,284,160

The request on the client ends up looking like - the token= query param is no longer there:

GET https://image.mux.com/8z7mnkC43KqXTHhpGz9fePf1Hxe1tCUk/storyboard.jpg

Defer media structural type checking in media-controller for custom elements.

If a custom element is loaded asynchronously via script tag, it is not guaranteed to be defined by the time the DOM is parsed/rendered and by the time the media-controller/media-container are checking for compatibility (currently simply checks if play is a property on the element instance).

We should be able to handle this use case by using a similar strategy that we do for checking mediaStateReceivers that are also custom elements, effectively deferring the check/set until after it's defined.

The current workaround is to rely on a defer="false" on the script tag, which leads to slower time to interactivity/time to first paint.

Support Safari's fullscreen API

Really thought they would have caught up on fullscreen API naming by now...

el.requestFullscreen does not work. Safari has el.webkitRequestFullScreen.

Which also means the other fullscreen related APIs are going to be different still.

Avoid hiding controls on play button click

Q: Is it possible to avoid player controls hiding on click play button until the user cursor is over it?

This is what happens when I use the default autohide

Screen.Recording.2022-01-19.at.6.28.00.PM.mov

This is what I'd like to do and I did dynamically setting autohide on video play/pause events

Screen.Recording.2022-01-19.at.6.28.53.PM.mov

<media-chrome-range/> elements not focusable via tabs in Safari

It looks like Safari does not respect focusable descendants in the shadow DOM. Our <media-chrome-button/> elements currently work since they are custom elements and the focusable element is the root itself.

A few things to note:

  • On quick investigation it looks like this may be a general issue w/Safari (See, e.g.: https://focus-style2.glitch.me from https://web.dev/style-focus/, where the <button/> in the example should be focusable via tabbing)
  • When VoiceOver is on on Mac, these elements are focusable by tab, so this at least shouldn't cause any obvious issues for a11y.

Simplify and expand ways media ui elements may associate themselves with a media-controller

  • Remove the need to add media-chrome-attributes attribute for custom media ui elements, so simply having observedAttributes with well-defined media ui attributes is sufficient for identifying a custom media ui element
    • Re-introduce whenDefined to (asynchronously) defer checking if a custom element is a media ui element until after it's been defined
    • Ensure custom elements containing media ui element descendants in their shadowRoot also work.
  • Add well-defined events as an alternative mechanism to associate/unassociate media ui elements to an ancestor (via event bubbling) to handle edge cases/as an "escape hatch" solution.

NOTE: After reviewing the Web Components Context Proposal, I believe this introduce unnecessary coupling between our "simple" media ui elements/components (which will be made even simpler by resolving this issue) and the media-controller. That said, it roughly parallels similar concepts in other frameworks (e.g. the React context, context Provider, and the assumed ancestor/descendant relationship), so we may want to revisit using this in some way as a potential shareable abstraction across target frameworks.

Volume Slider UI on Mobile

Maybe worth a discussion if this UI component should be shown at all if the device does not support changing volume via software. iPhone and other mobile devices can only change the volume via hardware buttons.

Improve DevEx by linking to a page that has details with explanations for common errors

If a developer uses media-chrome incorrectly or runs into a particular kind of error state, we should surface a link to a markdown page that has more details.

I noticed this with nextjs, errors say something like "See here for more info" with a link to a markdown page like this: https://github.com/vercel/next.js/blob/canary/errors/404-get-initial-props.md

The page shows why this error occurred, possible ways to fix it, and additional resources

This is one of those minor DevEx details that really warms my heart, I thought it was neat.

UI for linear advertisements

Requirements

Provide a set of components for displaying and controlling linear advertisements. The controls layer would provide functionality to:

  • Play/Pause ad playback (SSAI and CSAI)
  • Prevent UI based seeking
  • Provide a click-thru element
  • Display ad details like "Ad X fo Y"

Proposal 1

Create a <media-ad-controller> element which bootstraps the ad SDK and act as a wrapper element for a separate set of ad controls. The ad ui would use the standard media-* controls, i.e. buttons like play and fullscreen, and the <media-ad-controller> would intercept the MEDIA_X_REQUEST events and perform any ad specific logic.

<media-controller>
  <video slot="media"></video>
  <media-control-bar>
    <media-play-button />
    <media-mute-button />
    <media-volume-range />
    <media-time-range />
    <media-pip-button />
    <media-fullscreen-button />
  </media-control-bar>
  <media-ad-controller>
    <media-ad-info />
    <media-control-bar>
      <media-play-button />
      <media-mute-button />
      <media-volume-range />
      <media-time-range />
      <media-pip-button />
      <media-fullscreen-button />
    </media-control-bar>
  </media-ad-controller>
</media-controller>

Pros

  • Keeps the ad logic and controls contained to the <media-ad-controller> instead of having each component be aware of what type of media is playing and switching its logic accordingly.
  • A completely custom "ad view" can be achieved entirely in mark down by simply adding the desired controls as children of <media-ad-controller>. With a single control bar for both modes, the playback mode would need to be made available in a way that CSS and JS could be written to customize the control for the given mode.
  • In the future, if the library is ever delivered in an "unbundled" manner (individual ES6 modules), having that ad logic in a standalone component would allow for the ad code to be omitted entirely when not needed.

Cons

  • More verbose markdown at the page level.
  • The ad controller will need to be aware of the video element (ad SDK usually require a reference). Since the media element is not a child of <media-ad-controller> the reference would need to be injected some how:
    • Perhaps in a similar way to how state is passed down?
    • Sibling query selector?

Proposal 2

Similar to the first proposal but with the <media-ad-controller> wrapping the entire UI.

<media-controller>
  <media-ad-controller>
    <video slot="media"></video>
    <media-control-bar>
      <media-play-button />
      <media-mute-button />
      <media-volume-range />
      <media-time-range />
      <media-pip-button />
      <media-fullscreen-button />
    </media-control-bar>
  </media-ad-controller>
</media-controller>

Pros

  • Less verbose markdown at the page level.
  • Similar future "tree shaking" benefits as proposal one

Cons

  • No ability to create custom ad views in markdown. At minimum the <media-ad-controller> would need to have a mode attribute that could be used to create CSS selectors, i.e:
    media-ad-controller[mode="ad"] media-time-range { 
      pointer-events: none; 
    }
    

Other considerations

The current set of web components revolve around a stable public API: HTMLMediaElement. There is no similar standard for ad playback. When using a raw playback engine likehls.js or dash.js the ad implementation would need to be done separately. This could easily be encapsulated using <media-ad-controller> as a base class, and creating a ad-vendor specific element such as <ima-ad-controller>. For full featured players like Shaka and Video.js, ad APIs are provided directly by the SDK, or via a plugin. In those cases there would need to be a element that translates the player specific APIs into a normalized API that <media-ad-controller> could use. Similar to the way <youtube-video> provides an API to mirror HTMLMediaElement.

Define the minimum requirements for a media element

  1. The entire Video element API not not required to for a media elements, let's define explicitly what subset is required (maybe a media-element.md file in docs/) ?
  2. Let's also make sure we have some test coverage to make sure a minimal video element works on the normal happy paths

Discussion happened in this thread: #93 (comment)

update so classes get correctly applied with Styled JSX

styled-jsx is a popular method for css-in-js in the React ecosystem.

The way it works is like this:

function Home() {
  return (
    <div className="container">
      <h1>Hello Next.js</h1>
      <p>Let's explore different ways to style Next.js apps</p>
      <style jsx>{`
        .container {
          margin: 50px;
        }
        p {
          color: blue;
        }
      `}</style>
    </div>
  )
}

The p tag in this style only gets applied to this component. Internally, the library creates a unique class, and it applies that class to the HTML elements in the component AND the selectors in the CSS. So the DOM and CSS ends up looking like this:

<div class="container jsx-1234">
  <h1 class="jsx-1234">Hello Next.js</h1>
  <p class="jsx-1234">Let's explore different ways to style Next.js apps</p>
</div>

The css looks like:

<style>
  .container.jsx-1234 {
    margin: 50px;
  }
  p.jsx-1234 {
    color: blue;
  }
</style>

When I attempted to do this with media-container I got the following:

return (
  <div className="video-container">
    <media-container>
    </media-container>
    <styled jsx>{`
       .video-container {
          // some styles here
       }
       media-container {
          // these styles don't get applied
       }
    `}
    </styled>
  </div>
)

media-container-classname_2021-03-18_15-36-51

media-container classname="jsx-1234" should be media-container class="jsx-1234". It's almost as if styled-jsx things media-container is a react component and it's passing in className down and it ends up being an attribute on the web component.

There is a way to workaround this by using .video-container :global(media-container), but ideally the above code should work.

I don't know if the fix would be on the media-chrome side or the styled-jsx side to make this compatible. This issue might be relevant

Examples have layout issues in desktop safari fullscreen

In just the examples the controls seem to sit partially below the screen and the video doesn't fill the screen horizontally. This only happens in Safari desktop. It does not happen on the media-chrome.org homepage demo.

Haven't had a chance to dig into it, but it's worth understanding what's going on since it's our main examples.

Repo examples fullscreen

image

Media-chrome.org fullscreen

image

Text Track Data

Q: How do we pass text track data (captions, subtitles) in to the menus and other elements that need it?

Assumptions:

  • At the the UI (chrome) level we are not overlaying the captions on the media, that's the job of the media element
  • We may still want access to the text track cues, to display outside of the player or do something interesting based on a metadata track.

Important text track details:

  • srclang is required when kind is set
  • label is not required
  • "A media element cannot have more than one track with the same kind, srclang, and label."
  • Tracks can be disabled, hidden (still active and usable), and showing
  • Multiple tracks of the same kind can be showing

Proposal

Available tracks list:

  • One attr per 'kind' of track (Menus can choose to combine the lists if desired)
<media-ui-el media-captions-list="..." media-subtitles-list="..." >
  • Comma-separated list with URL-encoded optional label value
<media-ui-el media-captions-list="en-US:English en:English%20%28with%20descriptions%29">

Min required
<media-ui-el media-captions-list="en">

Selected track(s)

<media-ui-el media-captions-showing="en-US es">

Emit events from media-controller

Related to #41 we should re-emit the media events that happen so that applications can have a central source for them, rather than needing to listen to the media element itself (which could change).

This gets a little complicated with fullscreenchange events, because those actually happen on the media-controller itself. Ideally we can unify the event name rather than requiring the browser-specific solution in #41.

Update Icons

See #139 for reference icons and goals.

  • Icons should still respect all anticipated styling from Media Chrome (from css vars and well-defined component styles)
  • Examples should be updated as needed based on changes to icon dimensions.

Shouldn't media-controller auto-hide when a video is defined with the "autoplay" attribute?

Hi, I am currently testing the library in a WebView on iOS, using the following code:

<media-controller autohide="2">
    <video slot="media" autoplay>
        <source src="${ url }" type="${ mimeType }">
    </video>
    <media-control-bar>
        <media-play-button></media-play-button>
        <media-mute-button></media-mute-button>
        <media-time-range></media-time-range>
        <media-duration-display></media-duration-display>
    </media-control-bar>
</media-controller>

The problem is that users have to realize, they must touch the video after it starts autoplaying for the autohide attribute to kick in. Wouldn't it be more logical for autohide to be respected without requiring user interaction in this case? In other words: The video start playing automatically, then the controls auto-hide after 2 seconds (autohide="2").

Uncaught exception when using <youtube-video>

Hello, I'm trying out media-chrome with <youtube-video> element as suggested in your doc and the example I found. My code is simply:

<script type="module" src="https://unpkg.com/youtube-video-element@0"></script>
<script type="module" src="https://unpkg.com/[email protected]"></script>
...
<media-controller>
    <youtube-video slot="media" src="https://www.youtube.com/watch?v=rubNgGj3pYo"></youtube-video>
</media-controller>

This is the exception I encounter:
Screenshot from 2021-12-21 18-56-43

Happy to provide more details to help debugging!

New notes tab on Mac covers fullscreen button

Mac Monterey has a new feature where if you mouse to the bottom right of the screen, a little tab will pop up allowing you to create a new note (Apple Notes). The tab overlaps the default placement of the fullscreen button, creating a not so great experience. I think I was asked if I wanted to turn it on or not, so it might not affect everyone.

It feels like we should care, but interested in opinions on that. I'm not sure what a broad solution to that would look like. It'll be interesting to see what other players do with it.

image

[Feature Request - Extra] Point of interest indicator

It would be cool to have point in a video slider that were clickable (jumps to that section) to detonate points of interest. Perhaps even with a tooltip on hover.

Maybe something like this?
image

I know Youtube does something sort of similar with segments of a video. That would also be cool to add.

But I'm really not sure if this type of thing falls into this framework or not. Would be nice to hear some thoughts.

Bug - media-chrome crashes with a RTE on initial load when used with React (CRA or Next.js)

This is not in the current release, but was crashing in a demo branch and I believe was also crashing in main.

Stack trace:

media-container.js:104 Uncaught TypeError: Cannot read properties of null (reading 'nodeName')
    at HTMLElement.get media [as media] (media-container.js:104)
    at HTMLElement.registerMediaStateReceiver (media-controller.js:1)
    at t (media-controller.js:1)
    at A (media-controller.js:1)
    at $ (media-controller.js:1)
    at HTMLElement.associateElement (media-controller.js:1)
    at new b (media-controller.js:1)
    at createElement (react-dom.development.js:8995)
    at createInstance (react-dom.development.js:10192)
    at completeWork (react-dom.development.js:19464)
    at completeUnitOfWork (react-dom.development.js:22815)
    at performUnitOfWork (react-dom.development.js:22787)
    at workLoopSync (react-dom.development.js:22707)
    at renderRootSync (react-dom.development.js:22670)
    at performSyncWorkOnRoot (react-dom.development.js:22293)
    at scheduleUpdateOnFiber (react-dom.development.js:21881)
    at updateContainer (react-dom.development.js:25482)
    at react-dom.development.js:26021
    at unbatchedUpdates (react-dom.development.js:22431)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:26020)
    at Object.render (react-dom.development.js:26103)
    at Module.<anonymous> (index.js:7)
    at Module../src/index.js (index.js:18)
    at __webpack_require__ (bootstrap:856)
    at fn (bootstrap:150)
    at Object.1 (reportWebVitals.js:14)
    at __webpack_require__ (bootstrap:856)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

Access to events emitted

Hi,

Is there a way to access to events emitted by a media controller?

For example, I need to know when the player go fullscreen.
May you can emit an event attach to window with the id of the player element?
like so "enterFullscreen-myMediaControllerId@window"

How can I manage the dooble click to enter then exit fullscreen ?

Cordialement,

Proposal: work around styled-jsx `classname` attribute bug

vercel/styled-jsx#647 has been pretty much silent, so it might be worth it for us to workaround that issue ourselves.

The underlying problem is described in #24

TLDR is that custom elements end up getting an attribute classname instead of class.

Can we work around this by doing the following:

  • Observe classname attribute and assign it to the element's class

Are there any downsides or side-effects to doing this? Many, many people are going to run into this. styled-jsx is pretty widely used so we need to fix this in one way or the other otherwise developers are going to really have a BadTime ™️

cc:/ @mmcc -- had this idea when we were chatting

Sliding-out volume controls and the implications

Publishing my neurosis here for entertainment and in case anyone has an interesting view point.

I'm working on example of audio players, and I'm feeling compelled to use a volume control that reveals itself rather than is aways visible, because audio players tend to be on the smaller side.

For an example of sliding-out/revealing audio controls see the youtube player or the default chrome controls for audio (and video).

Because this requires a relationship between the mute-button and the volume-range, the possible implementations then balloon out of control, with various benefits and costs of each.

All that to say, I think the short term answer is to do nothing for now, and rely on the themes (Option E), at least until we have a clearer understanding of how theming will work and where the challenges will be.

Volume Control Notes

Option A: Set sibling relationship

<media-mute-button reveal-volume-range="asdf"></media-mute-button>
<media-volume-range id="asdf"></media-volume-range>

Positives

  • Control hierchy stays flat
  • No change to how you style the two components

Negatives

  • Need to use javascript to do the hiding.
    • Not the worst.
  • Tab order could be weird. You really want the next tab after the mute button to go to the volume control, otherwise it will get hidden. So volume really needs to come after or before the mute button
    • The volume range should reveal itself on focus either way

Option B: Child volume range

<media-mute-button>
  <media-volume-range></media-volume-range>
</media-mute-button>

Positives

  • Makes it easy to align volume to the mute button however is needed
  • Volume is still in the light dom, so no shadow dom challenges

Negatives

  • Styling challenges
    • Volume range has backgrounds, padding, etc, that need to be adusted now that it's in side the mute button. If a theme styles the volume range, we'll want some of those styles to apply (e.g. range handle styles), but not padding, backgrounds, etc.
  • Is tab order a challenge? Can you tab to child element from a parent?
  • Have to solve all the layout possibilities, or the most prominent ones

Option C: Single combined control

<media-volume-button reveal-volume></media-volume-button>

Positives

  • Simple concept
  • Could replace the other two

Negatives

  • Confusion around which volume elements to use and when
    • Unless this replaces the existing independent controls, but that could be pretty restricting
  • Have to solve all the mute/volume layout possibilities, or at least the most prominent ones

Option D: A parent element to combine them

<media-volume-control-set reveal-volume>
  <media-mute-button></media-mute-button>
  <media-volume-range></media-volume-range >
</media-volume-control-set>

Positives

  • Keep them independent controls, so styling looks relatively the same as other use cases.

Negatives

  • Creates hierarchy in the controls which can complicate theme styles
    • Today we use control-bar > * to style direct children of the control bar and avoid styling everything deeper. Couldn't do that anymore.
  • Does this create complication for themes? Do you have to account for someone using this set component? (I think a theme actually needs to be inclusive of the HTML).

Option E: Put it on the themes to handle

A very real option here is to not provide this feature at the component level. In the youtube them it's all in the CSS. It's a complex interaction that would be nice to simplify out of the box, but maybe not at the risk of making all other styling more complex.

<media-control-bar/> descendants should still be associable to the <media-controller/> via attribute

This issue is both a regression bugfix and an enhancement.

Previously, you could associate a <media-control-bar/>'s Media UI Elements to a <media-controller/> by setting its media-controller attribute value to a corresponding id, even if it wasn't a descendant of the <media-controller/>. This has since been broken after the first phase of rearchitecture. In addition, since ids must be globally unique on a DOM, we should instead allow the media-controller attribute to define any valid query selector string to locate/identify the relevant <media-controller/> (while still allowing for matching by id as a fallback).

Create loading indicator component

We had this for Demuxed, and want to make sure it gets added back:

<media-loading-indicator>

For demuxed, we were controlling is-loading attribute from the outside, but media-controller should be able to automatically handle the loading state based on media.readyState

Show/Hide Subtitle/CC Text Track Events

Q: What should events to show/hide subtitle/cc text tracks look like?

Assumptions:

  • Media Chrome Elements will receive attributes in the form proposed in #59
  • Elements will very likely need to parse these back into JS objects resembling a (partial) TextTrack
  • It's common to have a single control element for showing/hiding both Subtitles & CC
  • While uncommon, there are cases where users/players would want multiple Subtitles/CCs showing simultaneously.
  • It's common to have a UI that "disables"/hides any and all currently showing Subtitles & CC

Proposal

Create 2 generic events: one for showing and one for hiding 1+ subtitles/cc text tracks (or both)

Show Text Tracks

  • type: "mediashowtexttracksrequest"
  • detail (required): [{ kind: TEXT_TRACK_KIND, label?: OPTIONAL_TRACK_LABEL, language: TRACK_LANGUAGE }, ...] || { kind: TEXT_TRACK_KIND, label?: OPTIONAL_TRACK_LABEL, language: TRACK_LANGUAGE }

Result: changes any matching TextTrack to mode="showing" (NOTE: In this proposal, this would not change the mode of any currently "showing" TextTrack)

Examples:

// Example 1
const track = { kind: "captions", language: "en_US", label: "English (US)" };
const evt1 = new CustomEvent("mediashowtexttracksrequest", { composed: true, bubbles: true, detail: track });
this.dispatchEvent(evt1);

// Example 2 (multi-select)
const track1 = { kind: "captions", language: "en_US" }; // Assumes this caption track has no `label`
const track2 = { kind: "subtitles", label: "English (with descriptions)", language: "en_US" };
const evt2 = new CustomEvent("mediashowtexttracksrequest", { composed: true, bubbles: true, detail: [track1, track2] });
this.dispatchEvent(evt2);

Hide Text Tracks

  • type: "mediahidetexttracksrequest"
  • detail (optional): [{ kind: TEXT_TRACK_KIND, label?: OPTIONAL_TRACK_LABEL, language: TRACK_LANGUAGE }, ...] || { kind: TEXT_TRACK_KIND, label?: OPTIONAL_TRACK_LABEL, language: TRACK_LANGUAGE } || undefined

Result: if detail is present, changes any matching TextTrack to mode="disabled". If detail is not present, changes any TextTrack that currently has mode="showing" to mode="disabled".

Examples:

// Example 1
const track = { kind: "captions", language: "en_US", label: "English (US)" };
const evt1 = new CustomEvent("mediahidetexttracksrequest", { composed: true, bubbles: true, detail: track });
this.dispatchEvent(evt1);

// Example 2 (multi-select)
const track1 = { kind: "captions", language: "en_US" }; // Assumes this caption track has no `label`
const track2 = { kind: "subtitles", label: "English (with descriptions)", language: "en_US" };
const evt2 = new CustomEvent("mediahidetexttracksrequest", { composed: true, bubbles: true, detail: [track1, track2] });
this.dispatchEvent(evt2);

// Example 3 (disable/hide all currently showing)
const evt3 = new CustomEvent("mediahidetexttracksrequest", { composed: true, bubbles: true });
this.dispatchEvent(evt1);

CSS background vars

Not a biggie but in media-chrome I noticed a CSS var --media-control-background for the buttons and it’s set to the background-color property.

In a bunch of places in the themes etc this var is set to none but strictly that’s not valid CSS.
Should be transparent.
https://stackoverflow.com/a/8739704/268820

Maybe look into setting this CSS prop to the CSS shorthand background for more customization options.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.