繁体   English   中英

FFMPEG API-录制视频和音频-同步问题

[英]FFMPEG API - Recording video and audio - Syncing problems

我正在开发一个应用程序,它可以录制网络摄像头中的视频和麦克风中的音频。 我一直在使用QT,但不幸的是,摄像头模块在Windows上无法正常工作,这导致我使用ffmpeg录制视频/音频。

除了同步方面的轻微问题,我的相机模块现在运行良好。 音频和视频有时最终会以很小的差异不同步(我说少于1秒,尽管较长的录音可能会更糟)。

在对帧进行编码时,我以以下方式添加PTS(我来自muxing.c示例):

  • 对于视频帧,我将PTS逐一递增(从0开始)。
  • 对于音频帧,我将PTS递增音频帧的nb_samples (从0开始)。

我将文件保存为25 fps,并要求相机给我25 fps(可以)。 我还将视频帧转换为YUV420P格式。 对于音频帧转换,我需要使用AVAudioFifo因为微音发送的样本比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);
}

听起来您需要给帧(音频和视频)实时时间戳。 创建一个函数,该函数返回自开始捕获以来所经过的时间(以毫秒为单位)(整数)。 然后设置time_base每个流{1,1000}并设置pts每一帧到您的函数的返回值。 但请注意:您的时间戳不能小于或等于前一个时间戳。 因此,如果您一次获得数个帧,则需要丢弃帧(或编写另一种机制来处理这种情况)。

从我不再回答采取这里

在这里使用QElapsedTimer示例。

暂无
暂无

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

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