首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >利用MP4 AutoGen FFmpeg库同步音频/视频

利用MP4 AutoGen FFmpeg库同步音频/视频
EN

Stack Overflow用户
提问于 2016-07-05 07:54:04
回答 2查看 3K关注 0票数 1

我目前有问题,使我的音频和视频流保持同步。

这些是我正在使用的AVCodecContexts:

视频:

代码语言:javascript
代码运行次数:0
运行
复制
AVCodec* videoCodec = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264)
AVCodecContext* videoCodecContext = ffmpeg.avcodec_alloc_context3(videoCodec);
videoCodecContext->bit_rate = 400000;
videoCodecContext->width = 1280;
videoCodecContext->height = 720;
videoCodecContext->gop_size = 12;
videoCodecContext->max_b_frames = 1;
videoCodecContext->pix_fmt = videoCodec->pix_fmts[0];
videoCodecContext->codec_id = videoCodec->id;
videoCodecContext->codec_type = videoCodec->type;
videoCodecContext->time_base = new AVRational
{
    num = 1,
    den = 30
};

关于音频:

代码语言:javascript
代码运行次数:0
运行
复制
AVCodec* audioCodec = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_AAC)
AVCodecContext* audioCodecContext = ffmpeg.avcodec_alloc_context3(audioCodec);
audioCodecContext->bit_rate = 1280000;
audioCodecContext->sample_rate = 48000;
audioCodecContext->channels = 2;
audioCodecContext->channel_layout = ffmpeg.AV_CH_LAYOUT_STEREO;
audioCodecContext->frame_size = 1024;
audioCodecContext->sample_fmt = audioCodec->sample_fmts[0];
audioCodecContext->profile = ffmpeg.FF_PROFILE_AAC_LOW;
audioCodecContext->codec_id = audioCodec->id;
audioCodecContext->codec_type = audioCodec->type;

在编写视频帧时,我将PTS的位置设置为:

代码语言:javascript
代码运行次数:0
运行
复制
outputFrame->pts = frameIndex;  // The current index of the image frame being written

然后使用avcodec_encode_video2()对框架进行编码。在此之后,我调用以下代码来设置时间戳:

代码语言:javascript
代码运行次数:0
运行
复制
ffmpeg.av_packet_rescale_ts(&packet, videoCodecContext->time_base, videoStream->time_base);

这个弹奏得很完美。

但是,当我对音频做同样的处理时,视频以慢动作播放,首先播放音频,然后在没有声音的情况下继续播放视频。

我在任何地方都找不到如何在MP4文件中为视频/音频设置pt/dts位置的例子。任何帮助的例子都是很棒的!

另外,我首先要写视频帧,然后(一旦它们都写好了)我就会写音频。我用评论中建议的调整值更新了这个问题。

我上传了一个测试视频,在这里显示我的结果:124

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-12 10:31:35

解决了问题。我增加了一个新的功能来设置视频/音频位置后,设置帧PTS位置。

视频只是通常的增量(每帧加1),而音频是按以下方式完成的:

代码语言:javascript
代码运行次数:0
运行
复制
outputFrame->pts = ffmpeg.av_rescale_q(m_audioFrameSampleIncrement, new AVRational { num = 1, den = 48000 }, m_audioCodecContext->time_base);

m_audioFrameSampleIncrement += outputFrame->nb_samples;

在帧被编码后,我调用我的新函数:

代码语言:javascript
代码运行次数:0
运行
复制
private static void SetPacketProperties(ref AVPacket packet, AVCodecContext* codecContext, AVStream* stream)
{
    packet.pts = ffmpeg.av_rescale_q_rnd(packet.pts, codecContext->time_base, stream->time_base, AVRounding.AV_ROUND_NEAR_INF | AVRounding.AV_ROUND_PASS_MINMAX);
    packet.dts = ffmpeg.av_rescale_q_rnd(packet.dts, codecContext->time_base, stream->time_base, AVRounding.AV_ROUND_NEAR_INF | AVRounding.AV_ROUND_PASS_MINMAX);
    packet.duration = (int)ffmpeg.av_rescale_q(packet.duration, codecContext->time_base, stream->time_base);
    packet.stream_index = stream->index;
}
票数 1
EN

Stack Overflow用户

发布于 2016-07-06 18:01:20

PS:查看这篇关于带FFmpeg的A/V同步的文章/教程。如果下面没有的话可能会对你有帮助。

1)关于视音频时间戳的.

而不是使用当前的frameIndex作为时间戳,然后再使用重新标度。如果可能的话就跳过重放。

另一种方法是首先通过使用视频的帧每秒(FPS)来确保PTS值(在outputFrame->pts中)被正确创建。做这个..。

每个视频帧的:outputFrame->pts = (1000 / FPS) * frameIndex;

(对于30 FPS视频,帧1有0时间,到帧30“时钟”达到1秒。

因此,1000 / 30现在给每个视频帧一个33.333毫秒的表示间隔。当frameIndex为30时,我们可以说33.333 x 30 = 1000 m.secs (或1秒,确认每秒30帧)。

每个音频帧的:outputFrame->pts = ((1024 / 48000) * 1000) * frameIndex;

(由于48 the AAC帧的持续时间为21.333 m.secs,时间戳增加了该时间量。公式为:(1024 PCM / SampleRate) x 1000 ms/perSec,然后乘以帧索引)。

2)关于音频设置的.

位速率:

如果你的audioCodecContext->bit_rate = 64000;是48000赫兹(我想,你的位深是16位?)

尝试将96000128000作为最低起始值。

帧大小:

int AVCodecContext::frame_size的意思是“音频帧中每个频道的样本数”。

考虑到以上引用的Docs,并且MPEG AAC不做“每个通道”(因为两个L/R通道的数据包含在每个帧中)。每个AAC帧包含1024个PCM样本。

audioCodecContext->frame_size = 88200;的大小,您可以尝试= 1024;

配置文件:

我注意到你用MAIN作为AAC的配置文件。我习惯在视频里看到Low Complexity。我尝试了一些随机的MP4文件从不同的来源在我的硬盘,我找不到一个使用“主要”配置文件。作为最后的手段,测试“低复杂度”不会有什么影响。

尝试使用audioCodecContext->profile = ffmpeg.FF_PROFILE_AAC_LOW;

PS:检查这个可能的审咨委问题 (取决于您的FFmpeg版本)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38198052

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档