2015-05-22 20 views
16

Sto utilizzando WebRTC per inviare video da un server al browser client (utilizzando il server nativo WebRTC API e un server MCU WebRTC come Kurento).Sincronizzazione dei dati con video tramite WebRTC

Prima di inviarlo ai client, ogni fotogramma del video conteneva metadati (come i sottotitoli o qualsiasi altro contenuto applicativo). Sto cercando un modo per inviare questi metadati al client in modo che rimanga sincronizzato (al momento in cui è effettivamente presentato). Inoltre, vorrei poter accedere a questi dati dal lato client (tramite Javascript).

Alcune opzioni ho pensato:

  • l'invio dei dati da WebRTC DataChannel. Ma non so come garantire che i dati siano sincronizzati su una base per frame. Ma non sono riuscito a trovare un modo per garantire i dati inviati dal canale dati e il canale video è sincronizzato (di nuovo, spero di ottenere il livello di precisione del singolo fotogramma).
  • Invio manuale dei dati al client in qualche modo (WebRTC DataChannel, websocket, ecc.) Con data e ora che corrispondono ai timestamp del video. Tuttavia, anche se Kurento o altri server centrali conservano le informazioni relative al timestamp nel video, in base alla seguente risposta non esiste un modo applicativo per ottenere il timestamp del video dal javascript: How can use the webRTC Javascript API to access the outgoing audio RTP timestamp at the sender and the incoming audio RTP timestamp at the receiver?. Ho pensato di utilizzare l'evento timeupdate dell'elemento video standard, ma non so se funzionerà per il livello di precisione del fotogramma e non sono sicuro di cosa significhi in un video live come in WebRTC.
  • Inviare manualmente i dati e collegarli al video come un altro TextTrack. Quindi utilizzare onenter e onexit per leggerlo in modo sincronizzato: http://www.html5rocks.com/en/tutorials/track/basics/. Richiede ancora timestamp precisi, e non sono sicuro di sapere quali sono i timestamp e se Kurento li passa così com'è.
  • Utilizzo dell'API statistiche di WebRTC per contare manualmente i frame (utilizzando getstats) e sperare che le informazioni fornite da questa API siano precise.

Qual è il modo migliore per farlo e come risolvere i problemi che ho menzionato in entrambi i modi?

MODIFICA: È richiesta una sincronizzazione precisa (in risoluzione di non più di un singolo fotogramma) di metadati con la cornice appropriata.

+0

Non potrai mai ottenere flussi sincronizzati perfetti se li separi. È possibile implementare un sistema di buffering per garantire l'assenza di avanzamento finché non è disponibile un buffer accettabile in entrambi i flussi. La soluzione migliore è quella di dimenticare la perfetta corrispondenza fotogramma per fotogramma, se lo si desidera, quindi codificarlo nel flusso video come video al volo. A parte l'audio e la grafica, non riesco a pensare al motivo per cui avresti bisogno di una precisione così elevata. Si dimentica che il tempismo perfetto diventa molto più semplice. – Blindman67

+0

Grazie, buon punto. Ad ogni modo la domanda è su come farlo a livello di codice, supponendo che potrei garantire che il flusso di metadati sia già stato raggiunto nel browser prima del flusso video. Il tuo suggerimento di ricodificare il video sembra piacevole, ma devo ancora abbinare i tempi del flusso video e del flusso dei metadati. Non sono nemmeno sicuro che il middle server conservi i timestamp della presentazione. – MaMazav

+1

Gli stream multimediali forniscono un aiuto. Se stai usando un video HTML5 puoi usare il buffered per restituire un oggetto TimeRanges per farti sapere cosa è stato memorizzato nel buffer. L'interfaccia HTMLMediaElement fornisce currentTime come attributo di lettura read. Puoi usarlo per ottenere il tempo in secondi del video. Per ottenere il numero di fotogramma corrente 'frameNumber = Math.floor (videoElement.currentTime/frameRate);' Scrittura su currentTime causerà la ricerca del video fino a quel momento. – Blindman67

risposta

1

Sospetto che la quantità di dati per frame sia abbastanza piccola. Guarderei codificarlo in un'immagine di codice a barre 2D e posizionarlo in ogni fotogramma in un modo che non venga rimosso dalla compressione. In alternativa, basta codificare la data e l'ora in questo modo.

Quindi sul lato giocatore si guarda l'immagine in un particolare fotogramma e si ottengono i dati o se si.

2

Ok, prima consente di ottenere il video e l'audio usando getUserMedia e permette di rendere più dati grezzi usando

https://github.com/streamproc/MediaStreamRecorder

:

/* 
* 
* Video Streamer 
* 
*/ 


<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"> </script> 
<script> 

// FIREFOX 

var mediaConstraints = { 
    audio: !!navigator.mozGetUserMedia, // don't forget audio! 
    video: true       // don't forget video! 
}; 

navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError); 

function onMediaSuccess(stream) { 
    var mediaRecorder = new MediaStreamRecorder(stream); 
    mediaRecorder.mimeType = 'video/webm'; 
    mediaRecorder.ondataavailable = function (blob) { 
     // POST/PUT "Blob" using FormData/XHR2 

    }; 
    mediaRecorder.start(3000); 
} 

function onMediaError(e) { 
    console.error('media error', e); 
} 
</script> 



// CHROME 

var mediaConstraints = { 
    audio: true, 
    video: true 
}; 

navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError); 

function onMediaSuccess(stream) { 
    var multiStreamRecorder = new MultiStreamRecorder(stream); 
    multiStreamRecorder.video = yourVideoElement; // to get maximum accuracy 
    multiStreamRecorder.audioChannels = 1; 
    multiStreamRecorder.ondataavailable = function (blobs) { 
     // blobs.audio 
     // blobs.video 
    }; 
    multiStreamRecorder.start(3000); 
} 

function onMediaError(e) { 
    console.error('media error', e); 
} 

Ora è possibile inviare i dati tramite DataChannels e aggiungi i tuoi metadati, nel lato destinatario:

/* 
* 
* Video Receiver 
* 
*/ 


var ms = new MediaSource(); 

var video = document.querySelector('video'); 
video.src = window.URL.createObjectURL(ms); 

ms.addEventListener('sourceopen', function(e) { 
    var sourceBuffer = ms.addSourceBuffer('video/webm; codecs="vorbis,vp8"'); 
    sourceBuffer.appendBuffer(/* Video chunks here */); 
}, false); 
+0

Sembra una bella direzione. Tuttavia, non capisco ancora come posso SINCRONIZZARE i metadati al fotogramma video corretto? E comunque preferisco non usare MediaSource in quanto ha alcune limitazioni (ad esempio il segmento dovrebbe iniziare con il keyframe https://code.google.com/p/chromium/issues/detail?id=229412) – MaMazav

+1

Bene, hai i dati dei video , quindi ora puoi manipolarlo in un primo tentativo magari con i timer, e inserire più o meno latenza a seconda delle necessità, è l'unico modo che penso che abbiamo adesso, o non usare webRTC, andare per websocket. – Jairo

+0

I timer non sono abbastanza precisi per le mie esigenze. Websockets è una grande idea che ho già studiato, ma poi ho bisogno di usare MediaSource che ha i suoi svantaggi. – MaMazav

Problemi correlati