Emscripten编译FFmpeg调用avformat_open_input时tcp_open挂死求助
解决Emscripten编译FFmpeg在Web中无法打开HTTP文件的问题
你的问题核心是浏览器安全机制禁止了Emscripten编译程序发起的原始TCP连接——浏览器环境不允许直接建立TCP套接字,只能通过标准HTTP API(fetch/XHR)发起网络请求,而FFmpeg默认的HTTP实现基于原生TCP,因此会出现挂死情况。
以下是可行的解决方法:
编译FFmpeg时启用Emscripten网络适配
编译时必须指定让FFmpeg使用Emscripten提供的网络模拟层,禁用原生TCP支持。编译配置示例:emconfigure ./configure \ --target-os=none \ --arch=x86_32 \ --enable-cross-compile \ --disable-programs \ --disable-doc \ --enable-network \ --enable-protocol=http,https \ --disable-muxers \ --disable-demuxers \ # 按需添加其他禁用/启用项关键参数是
--enable-network,它会让Emscripten将FFmpeg的socket调用转换为浏览器兼容的网络请求。改用浏览器Fetch API预下载文件,再喂给FFmpeg
这是最可靠的方案,完全绕过FFmpeg的原生网络请求逻辑:- 用浏览器
fetch下载目标文件,转为ArrayBuffer - 将
ArrayBuffer复制到Emscripten的堆内存中 - 创建FFmpeg的
AVIOContext,指向堆内存中的数据 - 调用
avformat_open_input打开这个AVIOContext
C侧示例代码:
// 假设js侧已将文件数据放到堆的data_ptr位置,长度为data_len AVIOContext* io_ctx = avio_alloc_context((unsigned char*)data_ptr, data_len, 0, NULL, NULL, NULL, NULL); AVFormatContext* fmt_ctx = NULL; avformat_open_input(&fmt_ctx, "dummy", NULL, NULL); fmt_ctx->pb = io_ctx; avformat_find_stream_info(fmt_ctx, NULL); // 后续处理逻辑JS侧配合代码:
fetch('http://server.com/file.mpg') .then(res => res.arrayBuffer()) .then(buf => { const dataPtr = Module._malloc(buf.byteLength); Module.HEAPU8.set(new Uint8Array(buf), dataPtr); // 调用C侧处理函数,传入dataPtr和buf.byteLength Module._process_file(dataPtr, buf.byteLength); });- 用浏览器
检查服务器CORS配置
即使使用Emscripten的网络适配,浏览器仍会强制执行CORS策略。确保服务器返回的响应包含正确的CORS头,例如:Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET否则浏览器会拦截响应,导致FFmpeg无法获取数据。
内容的提问来源于stack exchange,提问作者Sergei
相关产品推荐
相关产品推荐

