GKE中FFmpeg编码视频上传GCS后时长为0的问题求助
问题描述
我开发了一个部署在GKE上的C++程序,流程为:用FFmpeg读取视频输入,经OpenGL处理后编码为单个输出视频。本地运行完全正常,无警告或Valgrind错误,但上传至Google Cloud Storage(GCS)时出现多种异常:
- 两种上传方式(签名URL通过curl上传、gcsfuse挂载存储桶上传)均出现问题
- 异常表现包括:生成0字节/44字节文件、文件大小正常(约500MB)但视频时长为0、生成0.4秒视频,偶尔能正常输出(概率极低)
- 日志无异常,FFmpeg和Valgrind均未报错;curl上传前本地视频正常,上传后损坏
- 基于FFmpeg的muxing.c示例编码,仅修改了
fill_yuv_image函数,代码如下:
void video_encoder::fill_yuv_image(AVFrame *frame, struct SwsContext *sws_context) { const int in_linesize[1] = { 4 * width }; //uint8_t* dest[4] = { rgb_data, NULL, NULL, NULL }; sws_context = sws_getContext( width, height, AV_PIX_FMT_RGBA, width, height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, 0, 0, 0); sws_scale(sws_context, (const uint8_t * const *)&rgb_data, in_linesize, 0, height, frame->data, frame->linesize); }
注:rgb_data为处理后的输入数据,该部分逻辑正常,无法提供可复现示例
当视频大小正常但时长为0时,使用mplayer播放的报错信息如下:
MPlayer 1.4 (Debian), built with gcc-11 (C) 2000-2019 MPlayer Team do_connect: could not connect to socket connect: No such file or directory Failed to open LIRC support. You will not be able to use your remote control. Playing /media/c36c2633-d4ee-4d37-825f-88ae54b86100. libavformat version 58.76.100 (external) libavformat file format detected. [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f2cba1168e0]moov atom not found LAVF_header: av_open_input_stream() failed libavformat file format detected. [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f2cba1168e0]moov atom not found LAVF_header: av_open_input_stream() failed RAWDV file format detected. VIDEO: [DVSD] 720x480 24bpp 29.970 fps 0.0 kbps ( 0.0 kbyte/s) X11 error: BadMatch (invalid parameter attributes) Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory [vdpau] Error when calling vdp_device_create_x11: 1 ========================================================================== Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family libavcodec version 58.134.100 (external) [dvvideo @ 0x7f2cb987a380]Requested frame threading with a custom get_buffer2() implementation which is not marked as thread safe. This is not supported anymore, make your callback thread-safe. Selected video codec: [ffdv] vfm: ffmpeg (FFmpeg DV) ========================================================================== Load subtitles in /media/ ========================================================================== Opening audio decoder: [libdv] Raw DV Audio Decoder Unknown/missing audio format -> no sound ADecoder init failed :( Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders [dvaudio @ 0x7f2cb987a380]Decoder requires channel count but channels not set Could not open codec. ADecoder init failed :( ADecoder init failed :( Cannot find codec for audio format 0x56444152. Audio: no sound Starting playback... [dvvideo @ 0x7f2cb987a380]could not find dv frame profile Error while decoding frame! [dvvideo @ 0x7f2cb987a380]could not find dv frame profile Error while decoding frame! V: 0.0 2/ 2 ??% ??% ??,?% 0 0 Exiting... (End of file)
补充:程序在VM上通过xvfb-run启动,不上传GCS时运行正常。
排查方向
- 检查FFmpeg编码收尾逻辑:从报错
moov atom not found来看,视频文件的索引元数据未正确写入。必须确保编码完成后调用av_write_trailer()完成文件收尾,同时确认av_write_header()调用成功,所有帧都正常写入。如果程序提前结束进程或关闭文件句柄,本地缓存可能掩盖问题,但上传时会导致文件残缺。 - 验证文件上传完整性:
- curl上传时,添加
--fail参数确保上传失败直接报错,上传前后对比本地文件与GCS文件的MD5哈希,确认数据无丢失篡改。 - gcsfuse挂载时,设置
--implicit-dirs --disable-http2调整挂载行为,写入完成后调用fsync()强制刷盘,避免缓存未同步到GCS就结束操作。
- curl上传时,添加
- 修复SwsContext内存泄漏:当前代码每次调用
fill_yuv_image都创建新的sws_context但未释放,会导致内存泄漏,长期运行可能引发资源不足导致编码异常。应初始化时创建一次上下文,编码完成后调用sws_freeContext()释放。 - 检查GKE资源限制:容器的CPU、内存或磁盘IO配额不足可能导致编码线程中断,文件写入不完整。查看容器OOM日志,适当调高资源限制。
- 确认xvfb环境一致性:GKE的xvfb分辨率、颜色深度需与本地一致,确保OpenGL渲染的帧数据完整写入
rgb_data,避免读取到不完整帧。 - 强制刷写文件缓存:上传前调用
fflush()(标准库写文件)或avio_flush()(FFmpeg AVIOContext),确保所有数据写入磁盘;gcsfuse挂载目录必须调用fsync()完成同步。
内容的提问来源于stack exchange,提问作者Turgut
相关产品推荐
相关产品推荐

