簡體   English   中英

如何用ffmpeg尋找X號框架?

[英]How can I seek to frame No. X with ffmpeg?

我正在寫一個視頻編輯器 ,我需要尋找精確的幀,知道幀號

stackoverflow上的其他帖子告訴我,ffmpeg可能會在搜索后給我一些破幀,這對於播放來說不是問題,但對於視頻編輯來說是個大問題。

我需要通過幀號來尋找, 而不是按時間來尋找,這在轉換為幀號時會變得不准確。

我讀過dranger的tuts(現在已經過時了),最后得到:

av_seek_frame(fmt_ctx, video_stream_id, frame, AVSEEK_FLAG_ANY);

它始終尋求No. 0幀,並始終return 0 ,這意味着成功。 然后我試着閱讀Blender的源代碼並發現它真的很復雜(也許我應該實現一個圖像緩沖區?)。

那么,有沒有簡單的方法來尋找一個只需要像seek(context, frame_number)這樣的簡單調用的框架(雖然獲得一個完整的框架,而不是一個完整的框架)? 或者,是否有任何輕量級庫可以簡化這個?

編輯:感謝praks411 ,我找到了解決方案:

void AV_seek(AV * av, size_t frame)
{
    int frame_delta = frame - av->frame_id;
    if (frame_delta < 0 || frame_delta > 5)
        av_seek_frame(av->fmt_ctx, av->video_stream_id,
                frame, AVSEEK_FLAG_BACKWARD);
    while (av->frame_id != frame)
        AV_read_frame(av);
}

void AV_read_frame(AV * av)
{
    AVPacket packet;
    int frame_done;

    while (av_read_frame(av->fmt_ctx, &packet) >= 0) {
        if (packet.stream_index == av->video_stream_id) {
            avcodec_decode_video2(av->codec_ctx, av->frame, &frame_done, &packet);
            if (frame_done) {
                ...
                av->frame_id = packet.dts;
                av_free_packet(&packet);
                return;
            }
        }
        av_free_packet(&packet);
    }
}

EDIT2:原來有一個庫: FFMS2 它是“基於FFmpeg的源庫,便於幀精確訪問”,並且是可移植的(至少在Windows和Linux上)。

av_seek_frame將僅基於關鍵幀的時間戳進行搜索。 因為它尋求關鍵幀,你可能無法得到你想要的。 因此,建議尋找最近的關鍵幀,然后逐幀讀取,以達到所需的幀。

但是,如果您正在處理固定的FPS值,則可以輕松地將時間戳映射到幀索引。

在尋找之前,如果您指定了流,則需要將您的時間轉換為AVStream.time_base單位。 avformat.h閱讀av_seek_frame ffmpeg文檔。

例如,如果你想尋找1.23秒的剪輯:

 double m_out_start_time = 1.23;
 int flgs = AVSEEK_FLAG_ANY;
 int seek_ts = (m_out_start_time*(m_in_vid_strm->time_base.den))/(m_in_vid_strm->time_base.num);
 if(av_seek_frame(m_informat, m_in_vid_strm_idx,seek_ts, flgs) < 0)
 {
     PRINT_MSG("Failed to seek Video ")
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM