【发布时间】:2018-10-26 20:05:01
【问题描述】:
在我的 Android 应用程序中使用 FFMpeg 库,我试图了解如何在音频文件中寻找一个非常精确的位置。
例如,我想将文件中的当前位置设置为帧#1234567(在以 44100 Hz 编码的文件中),这相当于在 27994.717 毫秒处查找。
为此,我尝试了以下方法:
// this:
av_seek_frame(formatContext, -1, 27994717, 0);
// or this:
av_seek_frame(formatContext, -1, 27994717, AVSEEK_FLAG_ANY);
// or even this:
avformat_seek_file(formatContext, -1, 27994617, 27994717, 27994817, 0);
使用以微秒为单位的位置给了我迄今为止最好的结果。
但由于某种原因,定位并不完全准确:当我从音频文件中提取样本时,它并没有完全从预期的位置开始。有大约 30-40 毫秒的轻微延迟(即使我寻找位置 0,令人惊讶的是......)。
我是否以正确的方式使用函数,甚至是正确的函数?
编辑
这是我获得职位的方法:
AVPacket packet;
AVStream *stream = NULL;
AVFormatContext *formatContext = NULL;
AVCodec *dec = NULL;
// initialization:
avformat_open_input(&formatContext, filename, NULL, NULL);
avformat_find_stream_info(formatContext, NULL);
int audio_stream_index = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
stream = formatContext->streams[audio_stream_index];
...
// later, when I extract samples, here is how I get my position, in microseconds:
av_read_frame(formatContext, &packet);
long position = (long) (1000000 * (packet.pts * ((float) stream->time_base.num / stream->time_base.den)));
感谢那段代码,我可以获得当前帧开始的位置(帧 = 样本块,大小取决于音频格式 - mp3 为 1152 个样本,ogg 为 128 到 1152 个样本,.. .)
问题是:我在position 中得到的值不准确:实际上大约晚了 30 毫秒。比如说1000000,实际位置大概是1030000...
我做错了什么?这是 FFMpeg 中的错误吗?
感谢您的帮助。
【问题讨论】:
-
我很想知道您的 actual 应用程序在哪里 40ms 延迟/偏移实际上很重要?对于大多数桌面应用程序或游戏来说,40 毫秒的延迟很可能是微不足道的。你在做什么,这实际上很重要?即使在视频中,40 毫秒的音频延迟也不太可能引起注意。
-
@JesperJuhl 因为我正在开发某种 DJ 应用程序,所以我正在混音的每首歌曲的位置必须尽可能精确(所以我尝试将延迟控制在 1 毫秒以下)
-
感谢您的解释。这是有道理的。
-
我想添加那个可能使用相同库的 MPlayer,也有定位故障。它总是在播放 mp3 时报告位置,并且定位到该位置或多或少是准确的,除非您使用“seek +-N sec”控件,之后报告的位置会出错,有时会在 5 分钟内出错记录。 MPlayer 问题的人工解决方法是以 2 倍到 4 倍的速度播放,而不是使用“向前搜索”功能。