簡體   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