Golang+FFmpeg通过管道输入生成MP4缩略图失败的解决方法
问题:Golang结合FFmpeg通过管道输入MP4生成缩略图失败
操作步骤
- 终端执行命令成功生成缩略图:
ffmpeg -i test.mp4 -ss 00:00:00 -vframes 1 thumbnail.jpg - Golang中直接指定文件路径执行命令,成功将结果输出到stdout:
cmd := exec.Command("ffmpeg", "-i", "test.mp4", "-ss", "00:00:00", "-vframes", "1", "-f", "image2pipe", "-") - 尝试读取视频文件到buffer,通过
pipe:传给FFmpeg时失败,相关代码:r, err := os.ReadFile("test.mp4") if err != nil { log.Fatalf("Failed to read video file: %v", err) } videoBuffer := bytes.NewReader(r) cmd := exec.Command("ffmpeg", "-i", "pipe:", "-ss", "00:00:00", "-vframes", "1", "-f", "image2pipe", "-") cmd.Stdin = videoBuffer // Capture output as bytes var out bytes.Buffer cmd.Stdout = &out var stderr bytes.Buffer cmd.Stderr = &stderr // Run the command err = cmd.Run() if err != nil { log.Fatalf("ffmpeg command failed: %v, stderr: %s", err, stderr.String()) } // Convert bytes to image.Image img, _, err := image.Decode(&out) if err != nil { log.Fatalf("Failed to decode thumbnail: %v", err) }
错误信息
2024/04/23 13:25:51 ffmpeg command failed: exit status 183, stderr: ffmpeg version 7.0 Copyright (c) 2000-2024 the FFmpeg developers built with Apple clang version 15.0.0 (clang-1500.3.9.4) configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.0 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --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-libopenvino --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon libavutil 59. 8.100 / 59. 8.100 libavcodec 61. 3.100 / 61. 3.100 libavformat 61. 1.100 / 61. 1.100 libavdevice 61. 1.100 / 61. 1.100 libavfilter 10. 1.100 / 10. 1.100 libswscale 8. 1.100 / 8. 1.100 libswresample 5. 1.100 / 5. 1.100 libpostproc 58. 1.100 / 58. 1.100 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x136504080] stream 0, offset 0x30: partial file [mov,mp4,m4a,3gp,3g2,mj2 @ 0x136504080] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none, 1920x1080, 3496 kb/s): unspecified pixel format Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.26.100 Duration: 00:00:02.01, start: 0.000000, bitrate: N/A Stream #0:0[0x1](und): Video: h264 (avc1 / 0x31637661), none, 1920x1080, 3496 kb/s, 25 fps, 25 tbr, 12800 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1[0x2](und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 96 kb/s (default) Metadata: handler_name : SoundHandler vendor_id : [0][0][0][0] Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> mjpeg (native)) [mov,mp4,m4a,3gp,3g2,mj2 @ 0x136504080] stream 0, offset 0x30: partial file [in#0/mov,mp4,m4a,3gp,3g2,mj2 @ 0x600001134000] Error during demuxing: Invalid data found when processing input Cannot determine format of input 0:0 after EOF [vf#0:0 @ 0x600001f2c000] Task finished with error code: -1094995529 (Invalid data found when processing input) [vf#0:0 @ 0x600001f2c000] Terminating thread with return code -1094995529 (Invalid data found when processing input) [vost#0:0/mjpeg @ 0x104a04650] Could not open encoder before EOF [vost#0:0/mjpeg @ 0x104a04650] Task finished with error code: -22 (Invalid argument) [vost#0:0/mjpeg @ 0x104a04650] Terminating thread with return code -22 (Invalid argument) [out#0/image2pipe @ 0x60000182c000] Nothing was written into output file, because at least one of its streams received no packets. frame= 0 fps=0.0 q=0.0 Lsize= 0KiB time=N/A bitrate=N/A speed=N/A Conversion failed!
已尝试添加-analyzeduration 10000M和-probesize 10000M参数,但问题依旧。
解决方案
1. 调整FFmpeg参数顺序与内容
FFmpeg处理管道输入时,参数顺序和显式声明会影响解析逻辑,修改命令如下:
cmd := exec.Command("ffmpeg", "-analyzeduration", "100M", "-probesize", "100M", "-ss", "00:00:00", // 将-ss移到-i前,实现快速定位,避免管道读取冗余数据 "-i", "pipe:", "-vframes", "1", "-pix_fmt", "yuv420p", // 显式指定像素格式,解决"unspecified pixel format"错误 "-f", "image2pipe", "-")
-ss前置:让FFmpeg先定位到目标时间点再处理输入,减少管道数据读取量-pix_fmt yuv420p:强制指定像素格式,解决元数据解析不全导致的格式识别失败- 调整
analyzeduration和probesize为合理值(100M足够覆盖多数MP4的元数据区域)
2. 改用文件流而非内存Buffer
os.ReadFile会将整个视频加载到内存,易引发FFmpeg的EOF判断错误,改为直接传入文件流:
videoFile, err := os.Open("test.mp4") if err != nil { log.Fatalf("Failed to open video file: %v", err) } defer videoFile.Close() cmd := exec.Command("ffmpeg", "-analyzeduration", "100M", "-probesize", "100M", "-ss", "00:00:00", "-i", "pipe:", "-vframes", "1", "-pix_fmt", "yuv420p", "-f", "image2pipe", "-") cmd.Stdin = videoFile // 直接传入文件流,模拟终端读取文件的原生行为
3. 显式指定输入格式(可选)
若仍存在格式识别问题,可强制声明输入格式为MP4:
cmd := exec.Command("ffmpeg", "-analyzeduration", "100M", "-probesize", "100M", "-ss", "00:00:00", "-f", "mp4", // 显式指定输入格式,避免FFmpeg自动识别错误 "-i", "pipe:", "-vframes", "1", "-pix_fmt", "yuv420p", "-f", "image2pipe", "-")
内容的提问来源于stack exchange,提问作者godvlpr
相关产品推荐
相关产品推荐

