代码之家  ›  专栏  ›  技术社区  ›  fguillen

Chrome MediaRecorder正在随机生成损坏的视频文件

  •  0
  • fguillen  · 技术社区  · 3 年前
    • Chrome:96.0.4664.55版(官方版本)(x86_64)
    • 系统:Mac Catalina 10.15.5

    我使用此代码从MediaRecorder生成小型独立视频:

    var mediaRecorder;
    var chunks;
    
    // call this function to start the process
    function startRecording(stream) {
      chunks = [];
    
      mediaRecorder = new MediaRecorder(stream, { mimeType: "video/webm; codecs=vp8" });
    
      mediaRecorder.ondataavailable = function (e) {
        chunks.push(e.data);
      };
    
      mediaRecorder.onstop = function () {
        actualChunks = chunks.splice(0, chunks.length);
        const blob = new Blob(actualChunks, { type: "video/webm; codecs=vp8" });
        uploadVideoPart(blob); // Upload to server
      };
    
      recordVideoChunk(stream);
    };
    
    function recordVideoChunk(stream) {
      mediaRecorder.start();
    
      setTimeout(function() {
        mediaRecorder.stop();
        recordVideoChunk(stream);
      }, 10000); // 10 seconds videos
    }
    

    问题是,生成的一些文件被认为已被ffmpeg损坏:

    ffmpeg-v错误-i 03_video_part_1638535340218.webm-f null-

    Error while decoding stream #0:0: Invalid data found when processing input
    

    有关该文件的详细信息:

    > ffprobe 03_video_part_1638535340218.webm
    ffprobe version 4.4.1 Copyright (c) 2007-2021 the FFmpeg developers
      built with Apple clang version 12.0.0 (clang-1200.0.32.29)
      configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4.1_3 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox
      libavutil      56. 70.100 / 56. 70.100
      libavcodec     58.134.100 / 58.134.100
      libavformat    58. 76.100 / 58. 76.100
      libavdevice    58. 13.100 / 58. 13.100
      libavfilter     7.110.100 /  7.110.100
      libavresample   4.  0.  0 /  4.  0.  0
      libswscale      5.  9.100 /  5.  9.100
      libswresample   3.  9.100 /  3.  9.100
      libpostproc    55.  9.100 / 55.  9.100
    Input #0, matroska,webm, from '03_video_part_1638535340218.webm':
      Metadata:
        encoder         : Chrome
      Duration: N/A, start: 0.000000, bitrate: N/A
      Stream #0:0(eng): Video: vp8, yuv420p(progressive), 1280x1236, SAR 1:1 DAR 320:309, 60 tbr, 1k tbn, 1k tbc (default)
        Metadata:
          alpha_mode      : 1
      Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
    

    错误并不总是发生,也不是在所有独立的视频中都会发生。

    我无法使用Firefox重现错误

    我已经将错误跟踪到浏览器本身,在我下载并通过ffmpeg检查的同一页面中创建链接。因此,消除了上传机制中可能的原因。文件已从原始位置损坏。

    第一个文件中似乎从未出现错误。

    我尝试过的事情

    使用其他编解码器:

    • “视频/webm;编解码器=vp9”
    • “视频/webm”
    0 回复  |  直到 3 年前
        1
  •  0
  •   fguillen    3 年前

    我移动了的创建 MediaRecorder 实例到递归函数,现在它正常工作:

    var mediaRecorder;
    var chunks;
    
    // call this function to start the process
    function startRecording(stream) {
      chunks = [];
    
      recordVideoChunk(stream);
    };
    
    function recordVideoChunk(stream) {
      mediaRecorder = new MediaRecorder(stream, { mimeType: "video/webm; codecs=vp8" });
    
      mediaRecorder.ondataavailable = function (e) {
        chunks.push(e.data);
      };
    
      mediaRecorder.onstop = function () {
        actualChunks = chunks.splice(0, chunks.length);
        const blob = new Blob(actualChunks, { type: "video/webm; codecs=vp8" });
        uploadVideoPart(blob); // Upload to server
      };
    
      mediaRecorder.start();
    
      setTimeout(function() {
        mediaRecorder.stop();
        recordVideoChunk(stream);
      }, 10000); // 10 seconds videos
    }
    

    我认为是某种种族状况让这场比赛成为了听众( ondataavailable onstop )不按正确的顺序调用,或者多次调用。。。老实说,我不知道真正的问题是什么,如果有更好的代码版本,我也可以创建它。

        2
  •  -1
  •   O. Jones    3 年前

    当一个或多个视频文件损坏时 ondataavailable() 大块不知怎么会丢失。

    在您的代码中 actualChunks = chunks.splice(0, chunks.length); 奇怪有两个原因。

    1. actualChunks 由于未声明而进入全球范围。它可以使用 const 公告这可能解释了你可能的种族状况。
    2. 没有必要。就这样吧。
    const blob = new Blob(chunks, { type: mediaRecorder.mimeType });
    

    专业提示 使用一个好的Javascript IDE。它会抱怨未声明的变量,并保存您的xxx脖子。

    推荐文章