【发布时间】:2024-04-16 16:00:01
【问题描述】:
我正在尝试使用 FFMPEG 库将 AAC 音频流写入 mp4 文件。我正在使用直接写入套接字的自定义 IO 上下文,因此我必须设置 ioContext->seekable = 0。为了完成这项工作,我必须在编写标题时添加“movflags”empty_moov 和 frag_keyframe。
将输出写入套接字另一端的文件后,我可以在 VLC 或 Windows Media Player 中播放该文件。但是,寻找文件中的特定位置在两个播放器中都无法正常工作。 WMP 也不会显示总时长,VLC 只会在音频结束时短暂闪烁。
有没有办法在复用时添加更多元数据,以便玩家能够将文件视为不是作为流写入的?通过套接字的传输不会突然中断,因此我可以在文件末尾写入元数据。我也提前知道总持续时间,所以如果可能的话,我可以将它添加到文件的标题中。我不能使用faststart 标志,因为这需要在写入套接字之前输出到可查找的文件。
更新: 我知道我可以在AVFormatContext 中设置持续时间,我可以在AVStream 中设置nb_frames 和avg_frame_rate。但是,它并不能解决我的问题。当我设置 codecContext 标志AV_CODEC_FLAG_QSCALE 时,VLC 似乎能够估计总时间。但是,搜索仍然不起作用。
【问题讨论】:
-
这个 link 可能会帮助您了解 MOV 标志的问题(单词搜索:
-movflags empty_moov并阅读其余部分)。所以你描述了问题,但应用程序的上下文是什么?正在接收音频并且您想建立一个 MP4 直到 X 数量然后保存到文件?为什么不先缓冲所有需要的 AAC,然后再编码成最终的 MP4?无论如何考虑:#所有音频帧都是关键帧,#如果没有元数据,MPEG解码器无法搜索,#尝试M4a输出然后重命名为MP4? -
PS:我习惯将 FFmpeg 作为一个进程(而不是直接导入的库),但作为一个正在运行的进程,我会使用
ffmpeg -i - -c:a libfdk_aac -b:a 128k output.mp4在这里我会使用-i -让它知道没有输入文件,而是重复将每个 AAC 帧的字节写入process.writeBytes(myAACframe);,直到 AAC 结束,我退出进程并有一个可播放的文件。简而言之,通过附加 AAC 帧动态构建的 MP4 文件可用。也许该逻辑中的某些内容可以帮助您? -
你为什么不直接回应而不是在没有回应的情况下将 100 个代表点烧掉?您可以添加可以帮助其他人帮助您的 cmets。如果您想要一个可搜索的 MP4 文件,请确保它具有元数据,因为这是 MPEG 解码器搜索的必要条件。 (这意味着失去
-movflags empty_moov & frag_keyframe,因为它们增加了问题)。我建议使用“过程”方法,因为这是一个简单的测试,无需担心您的完整代码是否正确(例如:nb_frames等)。它可以用 C++、Java 或 C# 完成,具体取决于您的语言... -
PS:我们在这里谈论的 AAC 的持续时间是多少?我仍然认为您最好的选择是将输入字节收集到缓冲区中,并在准备好时(得到 5?10?60 分钟?)只需复用到 MP4 并将其发送到套接字。请记住,FFmpeg 仅在文件创建完成后才添加元数据(除了这里它将从套接字中消失,因此它无法编辑字节,这与保存在内存或磁盘中以在发送前先更新元数据条目不同)。跨度>
-
@VC.One 抱歉没有回复。过去 2 天我没有在办公室,也没有解决这个问题。如果我早点阅读,您暗示所有音频帧都是关键帧可能会对我有所帮助。我只是玩弄这些标志,当我放下 empty_moov 时它就可以工作了。然后,当我将 frag_keyframe 与另一个碎片选项(字节或毫秒)交换时,它也会创建更小的碎片,而不是一个巨大的碎片。
标签: audio ffmpeg streaming mp4 aac