FFMPEG: 转换mpegts为mp4时出现错误:复用器不支持非可寻址输出。

23

当将mpegts通过管道传输给ffmpeg时,希望将其转换为mp4并传输到stdout。但是,ffmpeg会显示:“复用器不支持不可寻址的输出”。

经过大量的研究,我得出结论:由于寻址能力的限制,mp4不适合进行实时转码。所以本质上来说:MP4无法通过ffmpeg进行传输,这有点说得通。

但是,我没有一个连续的mpegts流,我只有5秒钟的块。

  • 这是我的一个1 mb *.ts文件
  • 请从管道中读取直到EOF
  • 如果你真的需要寻址,请使用缓冲区将其转换为mp4
  • 将完整的内部mp4缓冲区传输到stdout

我需要这些mp4块用于HTML5 MediaSource,分段不是问题,我使用mp4box.js,效果非常好。

问题:

  • FFMPEG能够执行这种内部缓冲吗?
  • 是否有更好的选择可供考虑?

本质上来说:我是否可以(以某种方式)与ffmpeg交互而不使用文件? 我当前的解决方案需要使用文件和轮询新块,非常丑陋。

如果您对我的ffmpeg命令感兴趣,请让我知道。


1
我只想直接与ffmpeg通信,例如:这是我的输入缓冲区,请给出输出缓冲区,而不创建文件。由于我的程序将ffmpeg作为子进程调用,因此我不想浪费计算机资源来处理仅用于广播的文件。这真的感觉像是与ffmpeg的接口问题。ffmpeg真的无法缓冲输出并分块发送,而不是分段流式传输吗?我不想一路下到C语言层面只是为了更改接口... - Kr0e
2个回答

32

既然你提到了片段化,那么你可以使用movflags启用它。每个关键帧开始的片段示例:

ffmpeg -i segment.ts -c copy -movflags frag_keyframe+empty_moov -f mp4 -

如果 moov 原子为空,则无需寻找,因此可以与管道一起使用。


2
虽然这种方法有点奏效,但它会破坏对MediaSource的插入,因为持续时间始终为0,随后的块无法很快地插入。整个mp4的东西真是让人头疼... MediaSource!为什么你不支持TS!!!另一种可能性是使用某种emscripten编译的ffmpeg,它具有虚拟内存文件系统。这基本上就是我在寻找的...一种告诉ffmpeg使用RAM中的内容的方法,我不需要ffmpeg的流媒体功能,因为我只处理彼此独立的5秒块。 - Kr0e
“-copyts” 有什么区别吗?你可以使用 RAM 磁盘作为第二个解决方案。 - aergistal
MSE 应该支持 MPEG-2 TS https://w3c.github.io/media-source/byte-stream-format-registry.html - aergistal
1
没错。但我现在看不到这种情况。也许在将来的版本中会出现。目前的现状总是建议在浏览器中将 ts 分段转换为 mp4,但很难找到可靠的库来实现这一点。而且在移动设备上,您不想转换这些东西...... 这仍然太前沿了。 - Kr0e
Firefox对以这种方式渲染的MP4不太友好,但是Chrome可以正常加载。无论如何,这是个很巧妙的技巧,而且对MOV文件也适用。 - Llama D'Attore

9
如果您可以接受没有真正的 mp4格式,那么使用ismv对于我来说实际上比手动调整movflags更好(在某些播放器中不会损坏搜索和总持续时间信息),根据ffmpeg格式文档ismv 格式类似于 mp4 ,但自动调整了 movflags 以进行流式传输,并且在我的意见中做得更好。
测试过的浏览器:Firefox,Chrome,VLC
ffmpeg -i input.mp4 -f ismv -

很遗憾,截至2020年12月19日,无论是此命令还是aergistal的答案生成的视频都无法上传到Twitter,因为Twitter的视频上传验证非常严格,需要使用最常见的mp4格式。因此,目前我仍然必须使用ffmpeg直接输出到文件而不是stdout,以便允许Twitter视频上传。但如果有人找到解决方法,我会非常乐意听取建议!


你可以输出到一个命名管道,这将允许使用标准文件输出但仍然保留在内存中。 - Fred Dufresne

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