RecordRTC,将视频块发送到服务器并在服务器端录制为 webm 或 mp4

问题描述 投票:0回答:1

大家好。目前我正在开发一个函数,可以通过使用 RecordRTC 中的 dataonavailable 函数在缓冲区数组上记录每个块,而不是停止记录并将其发送回服务器。然而,当我通过 socket.emit 将其作为编码的 64 数据或 bufferArray 发送到服务器时,最终的视频在三个扩展名下被损坏:x-matroska(MKV)、mp4、webM。因此,我可以询问文件最终损坏的原因以及如何解决此问题吗?


有关 webRTC 的信息:以下是您可以阅读更多相关信息的文档:https://github.com/muaz-khan/RecordRTC

P/S:我使用了1000次的拼接,并从5-10秒提前停止,仍然无法录制为短视频。


服务器 - 代码:

socket.on("SEND BLOB",buffer=>{
        function writeOrAppendData(data){
            var filePath = './'
            const fileExtension = '.webm'
            if (!fs.existsSync(filePath+'finalresult' + fileExtension)){
                console.log('write Original file')
                fs.writeFileSync(filePath+'finalresult' + fileExtension,data)
            }
            else {
                fs.appendFileSync(filePath+'finalresult' + fileExtension,data)
            }
        }
        console.log(buffer)
        if (buffer instanceof Buffer)
            writeOrAppendData(buffer)


    })

客户-代码:

const config = ({video:true,audio:true})
      this.setState({RTCStatus:"pending"})
      navigator.mediaDevices.getUserMedia(config).then( async stream=>{
          const candidateURL = this.candidateID
          const socketIO = io.connect(baseURL,{query: {candidateID:candidateURL }})
          //this.socketRef = io.connect(baseURL);
          this.stream = stream;
          this.socketRef.current = socketIO;
          //this.candidateVideoRef.current.srcObject = stream;
          this.screenSharingStream = await navigator.mediaDevices.getDisplayMedia(config);
          this.videoRecorder = new RecordRTC(this.screenSharingStream, {
            type: 'video',
            mimeType:"video/webm;codecs=avc1",
            //disableLogs: true,
            timeSlice: 1000,
            bitsPerSecond: 128000,
            ondataavailable:async function(blob) {
              console.log(blob)
              
              //var candidateVideo = document.getElementById('candidate-video')
              
              //candidateVideo.src =URL.createObjectURL(blob)
              console.log(candidateVideo)
             // this.candidateVideoRef.current.srcObject = URL.createObjectURL(blob)
              var reader = new FileReader();
              reader.readAsArrayBuffer(blob)
              reader.onloadend = function(){
                var buffer = reader.result;
                console.log(buffer)
                socketIO.emit('SEND BLOB',buffer)
              }
              //let blobData = await fetch(blob).then(r => r.blob()).then(blobFile => new File([blobFile], "record", { type: "video/mp4" }))
              //console.log(blobData)
              
            },
            
        });
          console.log('hey')
          this.videoRecorder.startRecording();
          this.setState({RTCStatus:this.videoRecorder.getState()})
///const sleep = m => new Promise(r => setTimeout(r, m));
          //await sleep(3000);
          
          //this.videoRecorder.stopRecording(async function(){
          //  
          //  socketIO.emit('END BLOB')
          //})//
          
    
  }
RTCStop = () =>{
    if (this.stream && this.screenSharingStream){
      const candidateURL = this.candidateID
      const socketIO = io.connect(baseURL,{query: {candidateID:candidateURL }})
      this.stream.getTracks().forEach((track)=>{
        if (track.readyState==='live') {
            track.stop()
            this.candidateVideoRef.current.style.display='none';
            this.videoRecorder.stopRecording(async function(){
              socketIO.emit('END BLOB')
              //let blob = await fetch(this.videoRecorder.getBlob()).then(r => r.blob()).then(blobFile => new File([blobFile], "record", { type: "video/mp4" }))
              //let blobDuration = await getBlobDuration(blob);
              //console.log(blobDuration+'seconds')
              //let data = new FormData()
              //console.log(blob);
              //data.append("videoDuration",blobDuration)
              //data.append(this.candidateID, blob)
              //console.log('axios not run');
              //await request().post('/c/video', data)
              //console.log('axios run');
              //let rest = await
              //this.setState({submitVideo: true})
            })
        }})
javascript socket.io video-streaming recordrtc
1个回答
0
投票

我在使用 recordRTC 时遇到了类似的问题。我很确定文件损坏的原因是因为在发送已记录的块时,分块的视频文件需要特定的元数据才能进行解码。该元数据可在记录的第一个块上找到。因此,当尝试播放视频时,如果它们没有合并成一个视频文件,它们将显示为已损坏。我通过将所有块合并成一个斑点来解决这个问题。

async function mergeChunksAndPlay() {
  console.log(chunks, "vid chuncks");
  const blobs = chunks.map(chunk => chunk.blob);
  const mergedBlob = new Blob(blobs, { type: 'video/webm' });
  const blobUrl = URL.createObjectURL(mergedBlob);
  downloadBlob(mergedBlob, `merged-video-${Date.now()}.webm`);

}

function downloadBlob(blob, filename) {
  const blobUrl = URL.createObjectURL(blob);
  const downloadLink = document.createElement('a');
  downloadLink.href = blobUrl;
  downloadLink.download = filename; // Provide a filename for the download

  // Append the link to the document and trigger the download
  document.body.appendChild(downloadLink);
  downloadLink.click();

  // Clean up by revoking the blob URL and removing the link
  URL.revokeObjectURL(blobUrl);
  document.body.removeChild(downloadLink);
}

如果您已将所有块保存到名为“chunks”的数组中,那么这将起作用,并且它将把合并的文件下载到您的浏览器。您应该可以从那里播放它。

© www.soinside.com 2019 - 2024. All rights reserved.