Search code examples
javascriptvideo.jsvideo-recording

textTrack() videojs is empty (m3u8 playlist)


---------------Introduction-------------------------------------

I'm working on an IP camera project in a gym. There are 16 cameras. Each camera films an apparatus, then broadcasts its content on a local network in rtsp. All rtsp streams are saved as an m3u8 playlist on a web server via ffmpeg. The ffmpeg command used is: ffmpeg -v verbose -rtsp_transport tcp -i rtsp://id:[email protected].%%x:554/h265Preview_01_main -preset ultrafast -map 0 -map -0:a -c :v copy -c:a copy -f hls -hls_time 1 -segment_time 2 -hls_list_size 2000 -hls_flags delete_segments+append_list+omit_endlist C:[...]\WebServer\Data%%x\Rec.m3u8

The web server displays the web pages of each apparatus area, The videos are then played via video-js.

So far everything is working fine (except for a few bugs / data corruption when retrieving the different video streams).

My concern comes from a feature that I would like to add.

Indeed I would like to be able to extract part of the video to then be able to recover this extract and publish it on the networks.

At first I looked at the MediaCapture API but it is not compatible with the tablets used (iOS 12.5).

---------------The Problem-------------------------------------

So I try to go through the recovery of the currently read segment, then send a php request to launch a script on the server which will go and recover this segment and the following ones (depending on the desired recording time) to merge them into an mp4 video.

My problem is that I can't retrieve this information....

I set useCueTags: true but textTracks() remains empty...

If anyone can help me see what I did wrong, thanks :)

Here is an example of one of the webpages


<?php include('../Headers.php'); ?>
<body>
<section>
    <button id="pointer">Point de Sauvegarde</button>
    <button id="download">Enregistrement du point de sauvegarde</button>
    <div class="slidecontainer">
        <input type="range" min="10" max="100" value="50" step="10" class="slider" id="TempoRec">           
        <pre id="slideroutput">
        </pre>
    </div>
</section>
<section>
    <div class="gauche">
        <video-js id="player" class="video-js vjs-fluid" controls preload="auto">
        </video-js>
    </div>
    <div class="droite">
        <video id="recording" controls loop  muted></video>
    </div>
</section>
<?php include('../footer.php'); ?>      
<script src="http://127.0.0.1/dist/video-js/video.js"></script>
<script src="http://127.0.0.1/dist/videojs-seek-buttons.min.js"></script>
<script src="http://127.0.0.1/dist/videojs-frame-by-frame.js"></script>
<script>
    var player = videojs('player',{liveui:true,playbackRates: [0.1,0.3,0.5,1],controlBar: {volumePanel:false,muteToggle:false}});
    player.src({
        src:'http://127.0.0.1/Data/12/ZoneArc.m3u8',
        type:'application/x-mpegURL',
        nativeTextTracks: false,
        nativeAudioTracks: false,
        nativeVideoTracks: false,
        overrideNative: true,
        useCueTags: true
    });
    player.seekButtons({
        forward: 5,
        back: 10
    });
    player.frametoframe({
        forward: 0.1,
        back: 0.1
    });
    let tracks = player.textTracks();
    var segmentMetadataTrack;
    console.log(tracks.length); 
    for (let i = 0; i < tracks.length; i++) {
    if (tracks[i].label === 'segment-metadata'){
        segmentMetadataTrack = tracks[i];
        let previousPlaylist;
        segmentMetadataTrack.on('cuechange', function(){
            let activeCue = segmentMetadataTrack.activeCues[0];
            if (activeCue) {
              if (previousPlaylist !== activeCue.value.uri) {
                console.log('Switched from rendition ' + previousPlaylist +
                            ' to rendition ' + activeCue.value.playlist);
              }
              previousPlaylist = activeCue.value.uri;
            }
        });
      }
    }   
    
</script>
</body></html>

I'm expecting the variable tracks to be filled with a least the segment-metadata track but it stay empty whatever i do...


Solution

  • You can add a listener for loadedmetadata and check for the tracks then. If you check too soon the track won't have been added yet.

    player.on('loadedmetadata', function() {
      console.log(player.textTracks().length);
    });