c++ - 使用 libwebm (VP8/Opus) 的无声视频 -- 同步音频 --

标签 c++ audio webm opus

我正在尝试创建一个非常简单的 webm(vp8/opus) 编码器,但是我无法让音频正常工作。

ffprobe 确实检测文件格式和持续时间

流 #1:0(eng):音频:opus,48000 Hz,单声道,fltp(默认)

VLC Media information dialog

视频可以在 VLC 和 Chrome 中正常播放,但没有音频,出于某种原因,音频 input bitrate 始终为 0

大部分音频编码代码复​​制自 https://github.com/fnordware/AdobeWebM/blob/master/src/premiere/WebM_Premiere_Export.cpp

相关代码如下:

static const long long kTimeScale = 1000000000LL;

MkvWriter writer;
writer.Open("video.webm");

Segment mux_seg;
mux_seg.Init(&writer);

// VPX encoding...

int16_t pcm[SAMPLES];
uint64_t audio_track_id = mux_seg.AddAudioTrack(SAMPLE_RATE, 1, 0);
mkvmuxer::AudioTrack *audioTrack = (mkvmuxer::AudioTrack*)mux_seg.GetTrackByNumber(audio_track_id);
audioTrack->set_codec_id(mkvmuxer::Tracks::kOpusCodecId);
audioTrack->set_seek_pre_roll(80000000);
OpusEncoder *encoder = opus_encoder_create(SAMPLE_RATE, 1, OPUS_APPLICATION_AUDIO, NULL);
opus_encoder_ctl(encoder, OPUS_SET_BITRATE(64000));
opus_int32 skip = 0;
opus_encoder_ctl(encoder, OPUS_GET_LOOKAHEAD(&skip));
audioTrack->set_codec_delay(skip * kTimeScale / SAMPLE_RATE);
mux_seg.CuesTrack(audio_track_id);
uint64_t currentAudioSample = 0;
uint64_t opus_ts = 0;
while(has_frame) {
  int bytes = opus_encode(encoder, pcm, SAMPLES, out, SAMPLES * 8);
  opus_ts = currentAudioSample * kTimeScale / SAMPLE_RATE;
  mux_seg.AddFrame(out, bytes, audio_track_id, opus_ts, true);
  currentAudioSample += SAMPLES;
}

opus_encoder_destroy(encoder);
mux_seg.Finalize();
writer.Close();

更新 #1: 看来问题是 WebM 要求音频和视频轨道是交错的。 但是我不知道如何同步音频。 我应该计算帧持续时间,然后编码等效的音频样本吗?

最佳答案

问题是我丢失了 OGG header 数据,并且音频帧时间戳不准确。

这里要完成的答案是编码器的伪代码。

const int kTicksPerSecond = 1000000000; // webm timescale
const int kTimeScale = kTicksPerSecond / FPS;
const int kTwoNanoSeconds = 1000000000;

init_opus_encoder();
audioTrack->set_seek_pre_roll(80000000);
audioTrack->set_codec_delay(opus_preskip);
audioTrack->SetCodecPrivate(ogg_header_data, ogg_header_size);

while(has_video_frame) {
  encode_vpx_frame();
  video_pts = frame_index * kTimeScale;
  muxer_segment.addFrame(frame_packet_data, packet_length, video_track_id, video_pts, packet_flags);
  // fill the video frames gap with OPUS audio samples
  while(audio_pts < video_pts + kTimeScale) {
    encode_opus_frame();
    muxer_segment.addFrame(opus_frame_data, opus_frame_data_length, audio_track_id, audio_pts, true /* keyframe */);
    audio_pts = curr_audio_samples * kTwoNanoSeconds / 48000;
    curr_audio_samples += 960;
  }
}

关于c++ - 使用 libwebm (VP8/Opus) 的无声视频 -- 同步音频 --,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35283025/

相关文章:

html5-video - Shaka 播放器做了哪些 <video> 标签单独做不到的事情?

c++ - struct __declspec(align(16)) sse_t 和 struct alignas(16) sse_t 有什么区别?

google-chrome - 悬停2018 2019可以在Chrome/Safari中自动播放声音吗?

c++ - 它不会编译并给出 "Selection cannot be launched and there are no recent launches” 错误。

c# - 如何防止数字因波动而变大

java - 如何将输入流连接到sounpool或mediaplayer?

ffmpeg - 在 ffmpeg 中,如何设置 "-option reserve_index_space=1k"?

c++ - vp9 编码器返回一个空数据包

c++ - 如何在qt中的QTableWidget中获取comboBox项后的行号

C++:返回类成员变量地址时,编译器强制为const *类型