オーディオとビデオを支える技術(8)- FFMPEGを使用して、ビデオの音声だけを保存する。
画像を再生した次は、音楽を再生していきます。
その一段目として、オーディオをファイルに保存するところまで行います。
画像の保存と、オーディオの保存ほとんど同じです。
画像の時は、sws_xxxといった関数を多く使いました。
オーディオの時には、swr_xxxといった関数を多く使います。
オーディオが持つ情報とは、
1 チャンネル
オーディオは、2つ、2:1つ、4つ、5:1つ、7:1つと、多くのオーディオを持つ場合があります。
いわゆる、モノラル、サラウンド、5:1chといったように何個の音が聞こえてくるか?といった問題です。
2 サンプリングレート
1秒間に、実行する標本化の回数を表す値です。
標準的なサンプリングレートとして44.1kHの場合一秒間に44100回分割したグラフを作ります。
3 ビットレート
音を何段階で表すかといった問題です。
標準的なビットレートが16bitの場合は、65536段階で分割します。
といった情報を持ちます。
プログラム
この3つの情報を考えながら画像ファイルと同様に、コンバートコンテキストの作成、
デコード、コンバートの操作を行うことで、音声の作成を行うことができます。
//audioの変換コンテキスト作成 if(pAudioCodecCtx->sample_fmt != AV_SAMPLE_FMT_S16){ audio_convert_ctx = swr_alloc_set_opts(NULL,audioChanel_out, AV_SAMPLE_FMT_S16,sample_rate, pAudioCodecCtx->channel_layout,pAudioCodecCtx->sample_fmt, pAudioCodecCtx->sample_rate,0,NULL); if(swr_init(audio_convert_ctx)<0){ cout << "swr init Failed " << endl; } cout << "swr convert init " << endl; convert_spe =true; out_audioChanels = av_get_channel_layout_nb_channels(pAudioCodecCtx->channel_layout); Sample_size = av_rescale_rnd(DEFAULT_NB_SAMPLE,sample_rate, pAudioCodecCtx->sample_rate, AV_ROUND_UP); MAX_Sample_size = Sample_size; ret = av_samples_alloc_array_and_samples(&out_Audiobuffer,&LineSize,out_audioChanels, DEFAULT_NB_SAMPLE,AV_SAMPLE_FMT_S16,1); if(ret < 0){ cout << "audio buffer not create" << endl; } cout << "audio buffer create" << endl; } else { convert_spe = false; } cout << "start" << endl; cout << "______________________________" << endl; while (1) { if(av_read_frame(pFormatCtx,audiopackt) < 0){ break; } if(audiopackt->stream_index ==audioStream) { readSize = avcodec_decode_audio4(pAudioCodecCtx,pAudioFrame,&got_Frame,audiopackt); if(readSize < 0){ cout << "length <0 .skip this frame" << endl; break; } if(got_Frame){ if(convert_spe){ Sample_size = av_rescale_rnd(pAudioFrame->nb_samples, sample_rate,pAudioFrame->sample_rate,AV_ROUND_UP); if(Sample_size > MAX_Sample_size){ //out_Audiobuffer初期化 av_freep(&out_Audiobuffer[0]); ret = av_samples_alloc(out_Audiobuffer,&LineSize,out_audioChanels ,Sample_size,AV_SAMPLE_FMT_S16,1); if(ret < 0){ cout << "faild allocate" << endl; break; } MAX_Sample_size = Sample_size; } //変換する ret = swr_convert(audio_convert_ctx,out_Audiobuffer,Sample_size ,(const uint8_t **)pAudioFrame->data,pAudioFrame->nb_samples); if(ret < 0){ cout << "faild allocate" << endl; break; } int buf_size = av_samples_get_buffer_size(&LineSize,out_audioChanels, Sample_size,AV_SAMPLE_FMT_S16,1); if(buf_size < 0){ cout << "Error while converting audio" << endl; break; } } av_free_packet(audiopackt); } } }
最後にこのファイルを保存して終わり
FILE *CacheFile; char *CacheFilename = "CacheFile.raw"; CacheFile = fopen(CacheFilename,"wb"); if(CacheFile==NULL){ cout << "Can't open Cache File" << endl; return -1; } cout << "open Cache File" << endl; ----省略------ fwrite(out_Audiobuffer[0],1,buf_size,CacheFile);
out_audiobufferのサイズは、char型と同じなので第二引数に1を入れ、第3引数のバッファーサイズは、av_sample_get_buffer_sizeから習得できます。
実行ファイルの中にCacheFile.rawがあるので、mp3に変換して、音楽ソフトから再生したら、ビデオの音声が流れます。
最終的なソースコード
シリーズ一覧 nakadasanda.hatenablog.jp