ugrás a tartalomhoz

Mediasource Api

alkony4 · 2022. Már. 23. (Sze), 17.58
Szervusztok!

A kérdés kissé összetett és sajnos nem nagyon tudom melyik topik felelne meg a kérdés feltételének (ha netán rossz a hely előre is sorry).

Szeretnék egy saját mediastreamet, saját stream player kialakításával megvalósítani.
Alapul az ffmpeg szegmentálási lehetőségét vettem amit azonos hosszúságú videókra oszt egy meglévő videót realtime.
ffmpeg -re -i input.mkv -map 0:v:0 -map 0:a:0 -c:v libx264 -pix_fmt yuv420p -vf scale=1280:720 -c:a copy -sample_rate 44100 -segment_time 2 -r 30 -g 1 -sc_threshold 0 -force_key_frames ""expr:gte(t,n_forced*1)"" -flags +cgop+low_delay -f segment -segment_format_options movflags=+empty_moov+omit_tfhd_offset+frag_keyframe+default_base_moof+isml -segment_list_type ext -segment_list {segment_file_dir} output_%d.mp4
Ezzel szépen létre is jönnek a szeletek amit aztán megetetek a mediasource extesnion apival. A módszer 'működik' is... azzal a hibával hogy, a képi és hangi anyag egy idő után elcsúszik egymástól. Ez csak chrome böngészőben következett eddig be, firefoxban nem.

A teszt környezet: OS: Win10, Browser: Chrome 98.0.4758.102, Ffmpeg: version 2022-02-24-git-8ef03c2ff1-full

A forrásom:
<video muted controls></video>

<script>
    segments = [];
    last_segment = 0;
    mimeCodec = 'video/mp4; codecs="avc1.64000d,mp4a.40.2"';
    timestampOffset = 0;
    video = document.querySelector('video');
    mediaSource = new MediaSource();
    video.src = URL.createObjectURL(mediaSource);
    sourceBuffer = null;
    segment_process = false;
    
    
    mediaSource.addEventListener('sourceopen', function(){
        sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        sourceBuffer.mode = 'segments';
        
        // Initialization
        const init_xhr = new XMLHttpRequest();
        init_xhr.open('get', 'init.mp4');
        init_xhr.setRequestHeader('Cache-Control', 'no-cache');
        init_xhr.responseType = 'arraybuffer';
        init_xhr.send();
        init_xhr.onload = function(){
            sourceBuffer.appendBuffer(init_xhr.response);
            sourceBuffer.addEventListener('updateend', event = function(){
                sourceBuffer.removeEventListener('updateend', event);
                sourceBuffer.timestampOffset = 0;
                sourceBuffer.remove(0,1);
                
                manifestInitialization(function(){
                    if (segments.length > 0 && segment_process == false){
                        segments = segments.slice(-1);
                        segmentProccess();
                    }
                });
            });
        };
    }.bind(mediaSource));
    
    
    setInterval(function(){
        manifestInitialization(function(){
            if (segments.length > 0 && segment_process == false){
                segmentProccess();
            }
        });
    },500);
    
    
    // Manifest Initialization
    function manifestInitialization(callback){
        const manifest_xhr = new XMLHttpRequest();
        
        manifest_xhr.open('get', 'ehls/manifest');
        manifest_xhr.setRequestHeader('Cache-Control', 'no-cache');
        manifest_xhr.responseType = 'text';
        manifest_xhr.send();
        
        manifest_xhr.onload = function(e){
            lines = manifest_xhr.responseText.split(/\r?\n/);
            lines.forEach(function(line){
                line = line.split(';');
                const segment = {id: Number(line[0]), file: line[1], duration: Number(line[2]), type: Number(line[3])};
                if (!objectInArray(segment, segments) && segment.id > last_segment){
                    segments.push(segment);
                    last_segment = segment.id;
                }
            });
            callback();
        };
    };
    
    
    // Segment Load
    function segmentProccess(){
        segment_process = true;
        segment = segments.shift();
        const segment_xhr = new XMLHttpRequest();
        segment_xhr.open('get', 'ehls/' + segment.file);
        segment_xhr.setRequestHeader('Cache-Control', 'no-cache');
        segment_xhr.responseType = 'arraybuffer';
        segment_xhr.send();
        segment_xhr.onload = function(){
            timestampOffset += segment.duration;
            sourceBuffer.appendBuffer(segment_xhr.response);
            sourceBuffer.addEventListener('updateend', event = function(){
                sourceBuffer.removeEventListener('updateend', event);
                    sourceBuffer.timestampOffset = timestampOffset;
                    video.oncanplay = function(){
                        video.play();
                    };
                    if (segments.length > 0){
                        segmentProccess();
                        }
                    else{
                        segment_process = false;
                        }
            });
        };
    };
    
    
    // Object in array
    function objectInArray(sObj, array){
        returnV = false;
        array.forEach(function(aObj){
            if (JSON.stringify(sObj) == JSON.stringify(aObj)){
                returnV = true;
            }
        });
        return returnV;
    };
    
</script>
Illetve chrome által az alábbi hibaüzenetekre lettem figyelmes: logpic

Akadt e bárkinek ehhez hasonló problémája? Mit rontok el és miként javítható ez szerintetek?

Megtisztelő válaszotok előre is köszönöm.