Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Paul Berberian
    @peaBerberian
    hi :)
    Julien
    @juleur
    does videoElement apply player bottom bar controls ?
    Paul Berberian
    @peaBerberian

    I'm not sure I understand the question completely so I will try to give a general answer. As I don't know your background, I'll begin from the browser and end with the RxPlayer, and I hope you will find an answer to your question.

    By default, a <video> element will not display any control in the UI. But browsers provide them when you add add the controls "boolean attribute" to it. A boolean attribute is just an attribute without a value. When set it is equivalent to a true value and when not set, it is equivalent to a false. So you can just add "controls" in the list of the video element's attributes like this: <video controls /> to display your default browser's controls.
    Those will be different from browser to browser but they will usually support the usual play/pause buttons, seeking bar and more. This is well documented in the standard here: https://html.spec.whatwg.org/multipage/media.html#user-interface

    What most applications are doing - instead of just relying on the browser's default UI - is to create their own. This is down simply by adding other elements to the page. The interaction with the video by interacting with them is entirely handled through JavaScript in that case (e.g. in JavaScript, videoElement.pause() will pause playback).

    This is what can be seen in the demo page of the RxPlayer: https://developers.canal-plus.com/rx-player/
    Here controls are entirely defined through JavaScript. It is actually a code specific for our demo, located in the demo directory at the root of the project.

    We had to define those in a demo page because the RxPlayer in itself doesn't define controls. It is a more low-level concept of a player in a sense than how the general public would imagine it. The RxPlayer only download video, audio and subtitles and display those in a video element. It relies on streaming formats (like DASH) to do so, and it provides APIs to allow an application to have control over its behavior such as playing/pausing, changing the current audio track...
    It is then the task of the application to create its own UI - such as controls - over this.
    Often the application calling the RxPlayer (or other player libraries like it) is also called a "player" - this does not help comprehension but that's how it is!

    The RxPlayer is in fact used in several products which do not have the same interface at all. Each one of them define their own elements in the page and usually link those to the RxPlayer API.

    Rag Patel
    @raag_1599_twitter
    Hello
    So, I want to understand the "getLicense" method for DRM configuration. Tutorial example shows it takes one argument i.e. "challenge" while description say it has two arguments i.e. message and messageType. Are this "challenge" and "message" one and the same. https://developers.canal-plus.com/rx-player/doc/pages/tutorials/contents_with_DRM.html#subchapter-The%20license-fetching%20logic
    @peaBerberian reply asap.
    Paul Berberian
    @peaBerberian

    Yes getLicense is actually called each time the CDM (the module decrypting the content inside the browser) gives us a "message" for the currently-playing content.
    In the great majority of cases, this will only be for licence requests.
    But technically, it can be for other types (https://www.w3.org/TR/encrypted-media/#dom-mediakeymessagetype) for example an "individualization-request". Again, you most likely won't need this and noone we work with do need this.

    This is why the tutorial example only make use of the first argument. When a message comes, you'll most likely never encounter any other cases that one just necessitating a license request.
    We're aware that this can be confusing. This callback was written that way and documented as such long ago and we did not change its interface to not break the API. We're thinking about splitting this callback into multiple APIs for a future major version.

    And yes the "challenge" argument is named "message" in the example. I'll rename it so it's easier to understand, thanks.
    Rag Patel
    @raag_1599_twitter

    Yes getLicense is actually called each time the CDM (the module decrypting the content inside the browser) gives us a "message" for the currently-playing content.
    In the great majority of cases, this will only be for licence requests.
    But technically, it can be for other types (https://www.w3.org/TR/encrypted-media/#dom-mediakeymessagetype) for example an "individualization-request". Again, you most likely won't need this and noone we work with do need this.

    This is why the tutorial example only make use of the first argument. When a message comes, you'll most likely never encounter any other cases that one just necessitating a license request.
    We're aware that this can be confusing. This callback was written that way and documented as such long ago and we did not change its interface to not break the API. We're thinking about splitting this callback into multiple APIs for a future major version.

    Thanks and Regards

    Rag Patel
    @raag_1599_twitter
    Hi
    Can you help me with this error:
    Uncaught EncryptedMediaError: EncryptedMediaError (KEY_UPDATE_ERROR) TypeError: Failed to execute 'update' on 'MediaKeySession': Rejected with system code (89)
    Paul Berberian
    @peaBerberian
    Hi,
    It appears that the license, as returned by getLicense's Promise, is found to be invalid by the CDM (part of the browser decrypting the content). Can you look at the response from the license server (it may be not in the right format - like wrapped in an object - or just not the right response at all - like an error message) ?
    On what platform/browser are you on?
    Rag Patel
    @raag_1599_twitter
    Browser is Chrome
    vended license is like this CAUSwgUKvAIIAxIQCuQRtZRasVgFt7DIvVtVHBi17OSpBSKOAjCCAQoCggEBAKU2UrYVOSDlcXajWhpEgGhqGraJtFdUPgu6plJGy9ViaRn5mhyXON5PXmw1krQdi0SLxf00FfIgnYFLpDfvNeItGn9rcx0RNPwP39PW7aW0Fbqi6VCaKWlR24kRpd7NQ4woyMXr7xlBWPwPNxK4xmR/
    I used this for proper conversion:
    var binaryString = $wnd.atob(vended_license);
    var len = binaryString.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
    }
    console.log("Succeed");
    resolve(bytes.buffer);
    I used to console.log for debugging
    Rag Patel
    @raag_1599_twitter
    Any follow-up?
    Paul Berberian
    @peaBerberian
    Hm you will have a problem here if the corresponding string does not only contain ASCII data.
    We may want to test with a proper Base64->Binary conversion. Can you check with the right function (base64ToBytes) at: https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727 ?
    Paul Berberian
    @peaBerberian
    (the problem I see, is that you're calling charCodeAt which is going to output UTF16 code points, 16 bits by 16 bits. Then you're putting each of them as a single element in an Uint8Array. This means that any value superior to 255 will be truncated here. You also will be removing every other byte.
    This logic seems only valid to transform an UTF-16 string to an ASCII or UTF8 (only containing ASCII data) array of bytes .
    If we're sure we're not in that case, we could be using Uint16Array instead but I'm unsure if there can be a loss when converting to a string with atob when the outputted value is not a valid UTF16 string.
    Here doing the base64->Binary conversion ourselves allow to not rely on string conversion in the meantime.)
    Rag Patel
    @raag_1599_twitter
    I didn't see any character out of 0-255 range
    Paul Berberian
    @peaBerberian
    Ok ok. It all depends on the thing we're converting and the data the CDM expects. Here, does it looks like a readable string after the atob call ? If not, it's probably just binary data.
    meladon1337
    @meladon1337

    Hey, i want to setup a background video on my page which wont effect pagespeed. The Video will be around 35mb so i think i have to "stream" it instead of normally add it via a video element.
    Is the rx-player capable of beeing used as background video?

    And a big questionamrk for me is: how do the videos get splitted in chunks? Is this a Task for the serverside? Or does the player do this?

    Paul Berberian
    @peaBerberian

    Hi,
    First, yes the RxPlayer can be used to play video in the background (through the videoElement argument given on instantiation which will here be a HTMLVideoElement placed by your application in the background).
    For your questions about how does the videos get splitted into chunks, it is done server-side. Usually it is done with the help of an application called a "packager" which takes a simple media file (like an mp4) in input and gives a Manifest files and its associated chunks in output. For an example, you can look at the shaka-packager (https://github.com/google/shaka-packager), an open-source packager.

    But all this is most-of-all useful when you have multiple audio and video qualities, multiple tracks, live contents and/or DRM.
    For a simple use-case like the one you're describing (a single on-demand video quality), you're probably better off just adding it "normally" through the src of the video element. In most browsers, it should be able to stream it (and not wait for the whole video to be downloaded) as you want it. You just have to make sure that the format and codecs of your video is supported by all the browsers and platforms you want to target.
    Also, if you want to autoplay it when the user enters your page you might also want to play it muted, as some browsers (like chrome) will sometimes block autoplay for video with sounds.

    meladon1337
    @meladon1337

    Hi,
    First, yes the RxPlayer can be used to play video in the background (through the videoElement argument given on instantiation which will here be a HTMLVideoElement placed by your application in the background).
    For your questions about how does the videos get splitted into chunks, it is done server-side. Usually it is done with the help of an application called a "packager" which takes a simple media file (like an mp4) in input and gives a Manifest files and its associated chunks in output. For an example, you can look at the shaka-packager (https://github.com/google/shaka-packager), an open-source packager.

    But all this is most-of-all useful when you have multiple audio and video qualities, multiple tracks, live contents and/or DRM.
    For a simple use-case like the one you're describing (a single on-demand video quality), you're probably better off just adding it "normally" through the src of the video element. In most browsers, it should be able to stream it (and not wait for the whole video to be downloaded) as you want it. You just have to make sure that the format and codecs of your video is supported by all the browsers and platforms you want to target.
    Also, if you want to autoplay it when the user enters your page you might also want to play it muted, as some browsers (like chrome) will sometimes block autoplay for video with sounds.

    so i dont have pagespeed disadvantages, if i use the video just with the video tag?

    Paul Berberian
    @peaBerberian
    I don't think so. At the very least, full video loading should not be a pre-condition for the loading of the page. So here, I don't think there will be a profit to gain from chunking the content.
    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    Hello ,
    I am new to react and using this plugin, how can I put in the control bar the option for the user to select the resolution of the video I am playing from a local dash server. Regards.
    Paul Berberian
    @peaBerberian

    Hi,

    First, I should say that the RxPlayer does not have an integrated control bar by default, nor a UI implementation.
    It is just a player library with an exposed (lower-level) API. The UI is usually implemented by the application importing the RxPlayer.
    We do have a demo page with an exposed UI, but this is just an example to showcase what the RxPlayer does. It is not exported by the RxPlayer package.

    If you want to create a UI where you let the user choose the quality of the video, you can use the getAvailableVideoBitrates method, which will list every video bitrates available for the current video track (or the current video AdaptationSet, in DASH parlance) and setVideoBitrate to set a video bitrate.
    You can find more information on those methods in the API documentation: https://developers.canal-plus.com/rx-player/doc/pages/api/index.html

    I stay available if you have more questions.

    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    Thanks for your answer, I will see the documentation, I will expose any questions here, greetings
    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    Hello, the player through the addEvent function of the player, can you hear the onClick event or does the player bring one?
    Paul Berberian
    @peaBerberian

    Hi,
    You don't have to go through the RxPlayer for browser-defined events such as "click".
    For example, if you want to catch when the user click on the media element, you can just add a "click" event handler directly to the element. With React and JSX, it would be a "onClick" prop directly on the <video> element in the JSX. The RxPlayer will have no problem with that as a click on the page doesn't change anything about the content that is being played.

    We do have multiple events that can be used as a replacement of browser events (for example "seeking"). In that case, both have their own definition but it's usually better to rely on the RxPlayer events.

    Orlando David Mir Fonseca
    @orlando.mir_gitlab

    Hi I have two problems:
    first:
    When I initialize my player I hear the event player.addEventListener ("availableVideoTracksChange", onVideoTrack); and this returns three tracks, well up to there, when the user selects one of the displayed tracks, it throws me the following exception error: No content loaded
    at Player.setVideoTrack (rx-player.js: 49011)
    at onChangeValueQuality (Player.js: 312)
    at HTMLUnknownElement.callCallback (react-dom.development.js: 188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js: 237)
    at invokeGuardedCallback (react-dom.development.js: 292)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js: 306)
    at executeDispatch (react-dom.development.js: 389) and I don't know why this happens.
    The second:
    when I want to change the playBackRate

    const onSetPlayBackRate = (e) => {
    const value = parseFloat (e.target.value);
    console.log ("onSetPlayBackRate:" + value);
    player.setPlaybackRate (value);
    };
    it does not produce any change, if you could help me gracefully in advance

    Paul Berberian
    @peaBerberian

    Hi,
    For the "No content loaded" error, this is weird. It means that no content is playing when you're calling setVideoTrack.
    Are you sure the video is still playing when you call that API? (You can check by calling getPlayerState).

    For setPlaybackRate, it should not be a problem whether a content is loaded or not, the last content loaded should inherit the last rate set.
    Does getPlaybackRate returns the playback rate you have set? What do you mean by "does not produce any change", the content is still playing at a rate of x1?

    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    yes, it stays at 1x speed, I'm going to try getPlayerState and tell you that it works for me, thanks for your answer.
    When I get the player's status it returns STOPPED, I don't understand why? The content is playing or at least it's what you see, if you could help me, the file is loaded from a local dash server which has a dash file already converted Could that have something to do with it?
    Paul Berberian
    @peaBerberian
    My guess is that some fatal error happened. Can you retrieve the error? (either player.getError() or the "error" event)
    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    In fact, I start converting the video on the server and transmit it live and in the transmission I try to change setVideoTrack but first I ask the player its status and it keeps returning Stopped, is this possible? I already put this player.addEventListener ("Error" , function (err) {
    console.log (The player crashed: $ {err.message});
    });
    but no error appears in the console, only the one that gave me before when I tried to change the videotrack No content loaded
    at Player.setVideoTrack (rx-player.js: 49011)
    at onChangeValueQuality (Player.js: 318), any suggestions ?, regards.
    Paul Berberian
    @peaBerberian
    Another theory is that the player is "ending" at some point (after which it automatically stops).
    Can you check and log the "playerStateChange" event? If it goes through the "ENDED" state, there might be something in the Manifest/MPD that makes it thinks the content has ended.
    Orlando David Mir Fonseca
    @orlando.mir_gitlab

    I am subscribed to the event
    player.addEventListener ("playerStateChange", onChageState); I'm going to send you a sample of the browser console so you can see that before trying to change the track it never goes through stopped, or ended, greetings.

    initPlayer player: [object Object]
    Player.js: 327 New video tracks: (3) [{…}, {…}, {…}]
    Chat.js: 182 This will run after 1 second!
    Player.js: 185 onChageState: LOADED
    Player.js: 195 The new content is loaded and ready to be played
    Player.js: 185 onChageState: PLAYING
    Player.js: 202 The content is currently playing
    Player.js: 185 onChageState: SEEKING
    Player.js: 212 The content is still seeking, waiting for new data
    Player.js: 185 onChageState: PLAYING
    Player.js: 202 The content is currently playing
    7Chat.js: 182 This will run after 1 second!
    Player.js: 314 set valueQuality: 2
    Player.js: 316 player state: STOPPED
    Player.js: 321 Error: No content loaded
    at Player.setVideoTrack (rx-player.js: 49011)
    at onChangeValueQuality (Player.js: 319)
    at HTMLUnknownElement.callCallback (react-dom.development.js: 188)

    Paul Berberian
    @peaBerberian

    Hm, that's difficult to say here.
    Something is making the player to stop, somewhere...
    There is a few way the player can retrieve itself in the STOPPED state. From what I can tell right now, we may be in one of the following situation

    • you re-loaded a video through loadVideo
    • you called stop or dispose
    • a fatal error happened

    Can you enable RxPlayer's logs (RxPlayer.LogLevel = "DEBUG")? At the very least we will see if it's another loadVideo call or an error

    Orlando David Mir Fonseca
    @orlando.mir_gitlab

    I am using RxPlayer with reactjs, I am new to this world of reactjs, to initialize the rxPlayer as follows

    const initPlayer = () => {
    player = new RxPlayer ({videoElement: document.getElementById ("video")});
    video = player.getVideoElement ();
    videoContainer = video.parentNode;
    console.log ("initPlayer player:" + player);
    player.loadVideo ({
    url: "http: // localhost: 8000 / output / streams / video1 / dash.mpd",
    transport: "dash",
    autoPlay: autoplay,
    });

         player.addEventListener ("playerStateChange", onChageState);
         player.addEventListener ("availableVideoTracksChange", onVideoTrack);
         player.addEventListener ("Error", function (err) {
             console.log (`The player crashed: $ {err.message}`);
         });
     };
    
     useEffect (() => {
         console.log ("useEffect initPlayer ()");
         initPlayer ();
    
     }, [channelData, autoplay]); Could she be doing something wrong? Regards.
    Paul Berberian
    @peaBerberian
    You listen to the "Error" event, you should listen for "error" instead. Perhaps we're just not seeing the corresponding error.
    Orlando David Mir Fonseca
    @orlando.mir_gitlab

    Traducir del: inglés
    468/5000
    do the following:
    const onChangeValueQuality = (e) => {
    console.log ("set valueQuality:" + e.target.value);
    const value = player.getPlayerState ();
    console.log ("player state:" + value);

         try {
             player.setVideoTrack (e.target.value);
         } catch (e) {
             const error = player.getError ();
             console.log ("error:" + error + "code:");
             console.log (e);
    
         }
    
     };

    and error tells me it is null.

    Orlando David Mir Fonseca
    @orlando.mir_gitlab
    Good I am trying to implement the navigation bar, does the player have an event that is executed when the getPosition changes to update my bar?
    Orlando David Mir Fonseca
    @orlando.mir_gitlab

    Good, I need help, I don't know what else to do, I have the following problem whether it loads dash content or directfile when I am going to advance to a position in the player or I am going to change the resolution, it tells me the following error, Error: player: no content loaded
    at Player.seekTo (rx-player.js: 48473)
    at onMouseClick (Player.js: 334)
    at HTMLUnknownElement.callCallback (react-dom.development.js: 188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js: 237)
    at invokeGuardedCallback (react-dom.development.js: 292)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js: 306)
    at executeDispatch (react-dom.development.js: 389)
    at executeDispatchesInOrder (react-dom.development.js: 414)
    at executeDispatchesAndRelease (react-dom.development.js: 3278)
    at executeDispatchesAndReleaseTopLevel (react-dom.development.js: 3287)
    at forEachAccumulated (react-dom.development.js: 3259)
    at runEventsInBatch (react-dom.development.js: 3304)
    at runExtractedPluginEventsInBatch (react-dom.development.js: 3514)
    at handleTopLevel (react-dom.development.js: 3558)
    at batchedEventUpdates $ 1 (react-dom.development.js: 21871)
    at batchedEventUpdates (react-dom.development.js: 795)
    at dispatchEventForLegacyPluginEventSystem (react-dom.development.js: 3568)
    at attemptToDispatchEvent (react-dom.development.js: 4267)
    at dispatchEvent (react-dom.development.js: 4189)
    at unstable_runWithPriority (scheduler.development.js: 653)
    at runWithPriority $ 1 (react-dom.development.js: 11039)
    at discreteUpdates $ 1 (react-dom.development.js: 21887)
    at discreteUpdates (react-dom.development.js: 806)
    at dispatchDiscreteEvent (react-dom.development.js: 4168)

    However, the video is reproduced, the curious thing is that before performing the action I ask for the status of the player and it tells me that it is Stopped, however I am subscribed to the player's events and in Stopped I have an alert to see if it passes through the but I never run the alert, and it goes through playing, I don't know why this happens, if you could help me, greetings

    Paul Berberian
    @peaBerberian

    does the player have an event that is executed when the getPosition changes to update my bar?

    We do have a positionUpdate event but the frequency at which it is sent might not be the one you want.
    If that's the case you can call getPosition with an interval while also relying on the player's states (through playerStateChange) to know when the user is seeking etc. (or even the seeking and seeked events).

    For the "no content loaded" error, it seems again that the RxPlayer thinks that the content is stopped when the seeking is done.
    It seems there is something that makes the player stop somewhere.
    Legal
    @morganlegal
    Hi I'm trying to develop a custom segmentLoader. I've tried with the example from the docs with an mpd file and 2 mp4 files (one audio track and one video track). As long as I'm using the default segment loader, this works fine. But as soon as I use the custom one only the first segments from each track are loaded. Then it happens nothing. No error.
    Here's the code of the loader:
    const segmentLoader =  (infos, callbacks) => {
    
      console.log('customSegmentLoader', infos)
      const xhr = new XMLHttpRequest();
      const sendingTime = performance.now();
    
      xhr.onload = function onXHRLoaded(r) {
        if (200 <= xhr.status && xhr.status < 300) {
          const duration = performance.now() - sendingTime;
          const size = r.total;
          const data = xhr.response;
          callbacks.resolve({ duration, size, data });
        } else {
          const err = new Error("didn't work");
          err.xhr = xhr;
          callbacks.reject(err);
        }
      };
    
      xhr.onprogress = function onXHRProgress(event) {
        const currentTime = performance.now();
        callbacks.progress({ type: "progress",
          value: { duration: currentTime - sendingTime,
            size: event.loaded,
            totalSize: event.total } });
      };
    
      xhr.onerror = function onXHRError() {
        const err = new Error("didn't work");
        err.xhr = xhr;
        callbacks.reject(err);
      };
    
      xhr.open("GET", infos.url);
      xhr.responseType = "arraybuffer";
    
      const range = infos.segment.range;
      if (range) {
        if (range[1] && range[1] !== Infinity) {
          xhr.setRequestHeader("Range", `bytes=${range[0]}-${range[1]}`);
        } else {
          xhr.setRequestHeader("Range", `bytes=${range[0]}-`);
        }
      }
    
      xhr.send();
    
      return () => {
        xhr.abort();
      };
    };
    Am I missing something or doing something wrong?