FFMPEG转换由MediaRecorder录制的WEBM/MP4音频文件为MP3时抛出错误。

3
我使用MediaRecorder来录制浏览器中的音频,然后将其上传到我的服务器(基于ARM架构的Linux机器-AWS Lambda函数,如果有必要)。根据浏览器类型,我从MediaRecorder获取MP4文件(用于Safari浏览器)或WEBM文件(用于其他所有浏览器)。音频被转换为Base64字符串,并通过FFMPEG发布到我的服务器上。 MediaRecorder 实现
const audioStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
const MediaRecorder = window['MediaRecorder'];
const mimeType = MediaRecorder.isTypeSupported('audio/webm') ? 'audio/webm' : 'audio/mp4';
const recordingFileExtension = MediaRecorder.isTypeSupported('audio/webm') ? 'webm' : 'mp4';
mediaRecorder = new MediaRecorder(audioStream, { mimeType });
mediaRecorder.ondataavailable = convertBlobAndUploadChunk;
mediaRecorder.start(30 * 1000); // timeslice needs to be in ms
// When user stops recording
mediaRecorder.stop();
audioStream.getTracks().forEach( t => { t.stop(); });
// To convert the audio blob to string
function convertBlobToBase64(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onload = () => {
            const tmpStr = reader.result.toString();
            resolve(tmpStr.substring(tmpStr.indexOf('base64,') + 7));
        };
        reader.onerror = error => reject(error);
    });
}

let blobCount = 0;
async function convertBlobAndUploadChunk(blobEvent) {
    if (!blobEvent.data || blobEvent.data.size === 0) return;

    blobCount++;

    const recordData = JSON.stringify({
        M: {
            blobCount,
            //some other meta data
        },
        D: await convertBlobToBase64(audioBlob),
    });

    await angularHttpClient.post(apiUrl, recordData, new HttpHeaders({
        'Content-Type': 'application/json',
        'x-api-key': apiKey,
    })).toPromise();
}

在我的服务器上,我将WEBM/MP4文件转换为MP3文件,以提高跨浏览器兼容性并启用刮擦功能。

后端Lambda实现

const FFMpegCommand = require('fluent-ffmpeg'); // v2.1.2
new FFMpegCommand()
        .input(originalFile)
        .on('end', (error, stdOut, stdError) => {
            if (error) {
                console.error(error);
            }
        })
        .save(convertedFile);

这通常情况下能够完美运行99.9%的时间,但是FFMPEG在0.1%的时间内会抛出以下错误之一:

错误1:处理输入时发现无效数据

读取文件头时出现错误

ffmpeg version 4.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2021 the 
FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
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
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7232f40] could not find corresponding trex (id 1)
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7232f40] could not find corresponding track id 0
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7232f40] trun track id unknown, no tfhd was found
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7232f40] error reading header
/tmp/long-filename-of-140chars-to-keep-files-unique.mp4: Invalid data found when processing input
< p > < em > EBML 头解析失败

ffmpeg version 4.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
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
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
[matroska,webm @ 0x7595f40] Format matroska,webm detected only with low score of 1, misdetection possible!
[matroska,webm @ 0x7595f40] EBML header parsing failed
/tmp/long-filename-of-140chars-to-keep-files-unique.webm: Invalid data found when processing input

没有具体细节

ffmpeg version 4.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
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
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
/tmp/long-filename-of-140chars-to-keep-files-unique.webm: Invalid data found when processing input
错误2:输出文件#0不包含任何流
ffmpeg version 4.4-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2021 the FFmpeg developers
built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
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
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
[mpegts @ 0x5d19f40] Format mpegts detected only with low score of 2, misdetection possible!
[mpegts @ 0x5d19f40] Could not detect TS packet size, defaulting to non-FEC/DVHS
Input #0, mpegts, from '/tmp/long-filename-of-140chars-to-keep-files-unique.webm':
Duration: N/A, bitrate: N/A
Output #0, mp3, to '/tmp/long-filename-of-140chars-to-keep-files-unique.mp3':
Output file #0 does not contain any stream

感谢阅读,非常感谢任何帮助/建议。


2
音频被转换为Base64字符串,并使用FFMPEG发布到我的服务器。这与您的问题可能无关,但请不要这样做。没有理由这样做。您正在增加大量额外的内存使用和33%的带宽,而没有任何好处。请改为发布二进制数据。 - Brad
1
在我的服务器上,我将WEBM/MP4文件转换为MP3文件,以获得更好的跨浏览器兼容性并启用刮擦功能。WebM和MP4文件非常兼容。您可以将音频轨道重新混合到相同的文件格式中以解决刮擦问题,这样就不会失去额外的音频质量。 - Brad
没有代码,我们无法提供更多帮助。正如@kesh所说,问题可能出在其他地方。你的数据已经混乱了。你可能错过了标题段或者将它们排列顺序错误了。但是,由于没有代码,我们真的无法帮助你。 - Brad
仍然缺少 convertBlobAndUploadChunk - Brad
这可能是最重要的部分... - Brad
显示剩余4条评论
1个回答

0

如果没有更多的代码,这个调试可能有点棘手,但我认为Brad说的有道理,听起来数据不完整或损坏了。

如果是损坏的数据被摄入,那么您可能需要考虑在转换之前放置一些内容以确保其有效。

作为概念验证,我创建了这个Dockerfile

FROM ubuntu:22.04
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update
RUN apt-get install -y ffmpeg

COPY valid.sh /valid.sh
RUN chmod 755 valid.sh

ENTRYPOINT [ "/valid.sh" ]

并创建了一个名为valid.sh的文件:

#!/bin/bash

export INPUT_FILE
export OUTPUT_FILE

echo Looking for ${INPUT_FILE} exporting to $OUTPUT_FILE

/usr/bin/ffmpeg -v error -i /input/${INPUT_FILE} -f null - 2>errors.log

if [[ $(cat errors.log) ]]; then
    echo "Errors found! Source video isn't valid."
    exit 1
fi

/usr/bin/ffmpeg -i /input/${INPUT_FILE} -vn -ab 128k -ar 44100 -y /output/${OUTPUT_FILE};

运行它:

docker build -t test ./
docker run -it --env INPUT_FILE=broken.webm --env OUTPUT_FILE=test123.mp3 --rm --name test -v C:/Users/me/Desktop/example:/input -v C:/Users/me/Desktop/output:/output test:latest

如果 webm 文件无效,则返回:
Looking for broken.webm exporting to test123.mp3
Errors found! Source video isn't valid.`

...否则:

Looking for working.webm exporting to test123.mp3
ffmpeg version 4.4.2-0ubuntu0.22.04.1 Copyright (c) 2000-2021 the FFmpeg developers
  built with gcc 11 (Ubuntu 11.2.0-19ubuntu1)
  configuration: --prefix=/usr --extra-version=0ubuntu0.22.04.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-librsvg --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  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
  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 '/input/working.webm':
  Metadata:
    encoder         : http://sourceforge.net/projects/yamka
    creation_time   : 2010-05-20T12:00:13.000000Z
  Duration: 00:01:57.70, start: 0.000000, bitrate: 582 kb/s
  Stream #0:0(eng): Video: vp8, yuv420p(progressive), 540x360, SAR 1:1 DAR 3:2, 23.98 fps, 23.98 tbr, 1k tbn, 1k tbc (default)
  Stream #0:1(eng): Audio: vorbis, 44100 Hz, mono, fltp (default)
Stream mapping:
  Stream #0:1 -> #0:0 (vorbis (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to '/output/test123.mp3':
  Metadata:
    TSSE            : Lavf58.76.100
  Stream #0:0(eng): Audio: mp3, 44100 Hz, mono, fltp, 128 kb/s (default)
    Metadata:
      encoder         : Lavc58.134.100 libmp3lame
size=    1840kB time=00:01:57.71 bitrate= 128.1kbits/s speed= 209x    
video:0kB audio:1840kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.024520%

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接