简体   繁体   English

使用FFMPEG将可搜索的AAC音频流写入MP4文件

[英]Write seekable AAC audio stream into MP4 file with FFMPEG

I'm trying to write an AAC audio stream into an mp4 file using the FFMPEG libraries. 我正在尝试使用FFMPEG库将AAC音频流写入mp4文件。 I am using a custom IO context that writes directly to a socket so I have to set ioContext->seekable = 0 . 我正在使用直接写入套接字的自定义IO上下文,所以我必须设置ioContext->seekable = 0 To make this work I had to add the "movflags" empty_moov and frag_keyframe when writing the header. 为了完成这项工作,我必须在编写标题时添加“movflags” empty_moovfrag_keyframe

After writing the output to a file on the other end of the socket, I can play the file in VLC or Windows Media Player. 将输出写入套接字另一端的文件后,我可以在VLC或Windows Media Player中播放该文件。 However, seeking to a specific position in the file is not working properly in both players. 但是,寻找文件中的特定位置在两个玩家中都不能正常工作。 WMP also does not show the total duration and VLC only flashes it shortly when reaching the end of the audio. WMP也没有显示总持续时间,VLC仅在到达音频结束时很快闪烁。

Is there a way to add more metadata when muxing so the players are able to treat the file as if it was not written as a stream? 有没有办法在多路复用时添加更多元数据,以便玩家能够将文件看作是不是作为流写入? Transfer via the socket is not interrupted abruptly, so I could write metadata at the end of the file. 通过套接字传输不会突然中断,因此我可以在文件末尾写入元数据。 I also know the total duration in advance, so I could add it to the header of the file if it was possible. 我也提前知道总持续时间,所以如果可能的话我可以将它添加到文件的标题中。 I cannot use the faststart flag because this would require output to a seekable file before writing to the socket. 我不能使用faststart标志,因为这需要在写入套接字之前输出到可搜索文件。

Update: I learned that I can set the duration in AVFormatContext and I can set nb_frames and avg_frame_rate in AVStream . 更新:我知道我可以设置时间AVFormatContext ,我可以设置nb_framesavg_frame_rateAVStream However, it doesn't solve my problem. 但是,它并没有解决我的问题。 When I set the codecContext flag AV_CODEC_FLAG_QSCALE , VLC seems to be able to estimate the total time. 当我设置codecContext标志AV_CODEC_FLAG_QSCALE ,VLC似乎能够估计总时间。 However, seeking still doesn't work. 但是,寻求仍然不起作用。

If you want a seekable MP4 file make sure it definately has metadata as that's a neccessity for MPEG decoders to handle seeking (the MP4 metadata lists the start positions of each AAC frame's bytes. 如果你想要一个可搜索的MP4文件,请确保它肯定有元数据,因为这是MPEG解码器处理搜索的必要条件(MP4元数据列出了每个AAC帧的字节的起始位置)。
This means lose that -movflags empty_moov & frag_keyframe since they add to the problem. 这意味着丢失-movflags empty_moov & frag_keyframe因为它们会增加问题。

Consider: 考虑:

  • You don't need frag_keyframe since all audio frames are classed as keyframes. 您不需要frag_keyframe因为所有音频帧都被归类为关键帧。
  • Don't force empty_moov since MP4 decoders can't seek if there is no metadata. 不要强制执行empty_moov因为如果没有元数据,MP4解码器将无法搜索。 (FFmpeg wll take care of metadata in fragmentation mode). (FFmpeg将在碎片模式下处理元数据)。

A quote from this excellent guide on streaming : 这篇优秀的流媒体指南引用:

Writing a fragmented file has the advantage that the file is decodable even if the writing is interrupted (while a normal MOV/MP4 is undecodable if it is not properly finished), and it requires less memory when writing very long files (since writing normal MOV/MP4 files stores info about every single packet in memory until the file is closed). 编写碎片文件的优点是,即使写入被中断,文件也是可解码的(正常MOV / MP4如果未正确完成则不可编码),并且在写入非常长的文件时需要更少的内存(因为写入正常的MOV) / MP4文件存储有关内存中每个数据包的信息,直到文件关闭为止。 The downside is that it is less compatible with other applications . 缺点是它less compatible with other applications

Options you could try are: 您可以尝试的选项是:

  • frag_duration [num] Create fragments that are num milliseconds long. frag_duration [num]创建num毫秒长的片段。
  • frag_size [num] Create fragments that contain up to num bytes size of payload. frag_size [num]创建包含最多num字节大小的有效负载的片段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM