【发布时间】:2015-07-24 18:41:59
【问题描述】:
我正在开发一个应用程序,它能够录制来自网络摄像头的视频和来自麦克风的音频。我一直在使用 QT,但不幸的是相机模块在 Windows 上不起作用,这导致我使用 ffmpeg 来录制视频/音频。
我的相机模块现在运行良好,除了同步出现小问题。音频和视频有时会因微小的差异而不同步(我会说不到 1 秒,尽管较长的录音可能会更糟)。
当我对帧进行编码时,我按以下方式添加 PTS(我取自 muxing.c 示例):
- 对于视频帧,我将 PTS 逐一递增(从 0 开始)。
- 对于音频帧,我将 PTS 增加音频帧的
nb_samples(从 0 开始)。
我正在以 25 fps 的速度保存文件,并要求相机给我 25 fps(它可以)。我还将视频帧转换为YUV420P 格式。对于音频帧转换,我需要使用AVAudioFifo,因为 microfone 发送的样本比 mp4 流支持的更大,所以我必须将它们分成块。我为此使用了transcode.c 示例。
我不知道应该如何同步音频和视频。我需要使用时钟或其他东西来正确同步两个流吗?
完整代码太大,无法在此处发布,但如果有必要,我可以将其添加到 github,例如。
下面是写框架的代码:
int FFCapture::writeFrame(const AVRational *time_base, AVStream *stream, AVPacket *pkt) {
/* rescale output packet timestamp values from codec to stream timebase */
av_packet_rescale_ts(pkt, *time_base, stream->time_base);
pkt->stream_index = stream->index;
/* Write the compressed frame to the media file. */
return av_interleaved_write_frame(oFormatContext, pkt);
}
获取经过时间的代码:
qint64 FFCapture::getElapsedTime(qint64 *previousTime) {
qint64 newTime = timer.elapsed();
if(newTime > *previousTime) {
*previousTime = newTime;
return newTime;
}
return -1;
}
添加PTS的代码(分别是视频和音频流):
qint64 time = getElapsedTime(&previousVideoTime);
if(time >= 0) outFrame->pts = time;
//if(time >= 0) outFrame->pts = av_rescale_q(time, outStream.videoStream->codec->time_base, outStream.videoStream->time_base);
qint64 time = getElapsedTime(&previousAudioTime);
if(time >= 0) {
AVRational aux;
aux.num = 1;
aux.den = 1000;
outFrame->pts = time;
//outFrame->pts = av_rescale_q(time, aux, outStream.audioStream->time_base);
}
【问题讨论】: