基于FFmpeg, 实现 8k 16bit 立体声 转码 16k 16bit 单声道。

在这里插入图片描述

基于FFmpeg, 实现 8k 16bit 立体声 转码 16k 16bit 单声道。

命令 🐳​
	ffmpeg -i original.wav -ac 1 -ar 16000 new.wav
CODE 🚀​
  1. 设置重采样数据

    1. 输入: 立体声, 双通道, 8k, 16bit
      输出: 单声道, 单通道, 16k, 16bit

    2. // 准备重采样
        	struct SwrContext* swr = swr_alloc();
        	av_opt_set_int(swr, "in_channel_count", pCodecCtx->channels, 0);
        	av_opt_set_int(swr, "out_channel_count", DST_CHANNELS, 0);
        	av_opt_set_int(swr, "in_channel_layout", pCodecCtx->channel_layout, 0);
        	av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_MONO, 0);
        	av_opt_set_int(swr, "in_sample_rate", pCodecCtx->sample_rate, 0);
        	av_opt_set_int(swr, "out_sample_rate", DST_SAMPLE_RATE, 0);
        	av_opt_set_sample_fmt(swr, "in_sample_fmt", pCodecCtx->sample_fmt, 0);
        	av_opt_set_sample_fmt(swr, "out_sample_fmt", DST_SAMPLE_FMT, 0);
        	// 初始化
        	swr_init(swr);
        	if (!swr_is_initialized(swr)) {
        		fprintf(stderr, "Resampler has not been properly initialized\n");
        		return NULL;
        	}
      
  2. 重采样

    1. 解码一帧音频

      1. // 解码一帧音频
        if (avcodec_decode_audio4(pCodecCtx, frame, &gotFrame, &packet) < 0) 
          	break;
          		
        if (!gotFrame) {
          	printf("avcodec_decode_audio4 error. \n");
          	continue;
         }
        
    2. 计算实际重采样后得到的数据大小, 然后重新分配缓存

      1. int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr, DST_SAMPLE_RATE) +  frame->nb_samples,DST_SAMPLE_RATE, pCodecCtx->sample_rate, AV_ROUND_UP);
        
    3. 由于双声道转单声道,所以输入的通道个数等于输出通道个数的2倍。

      1. int outSize = dst_nb_samples * 2;
        int inSize = frame->nb_samples;
        
    4. 据音频格式分配相应大小的内存空间

      1. uint8_t** buffer;
        av_samples_alloc((uint8_t**)&buffer, NULL, DST_CHANNELS, outSize,  DST_SAMPLE_FMT, 0);
        
    5. 进行重采样

      1. // 重采样
         int frame_count = swr_convert(swr, (uint8_t**)&buffer, outSize,
        	(const uint8_t**)frame->data, inSize);
        
         if (frame_count < 0) {
        	av_freep(&buffer);
        	printf("swr_convert error\n");
        	break;
          }
        
    6. 获取给定音频参数所需的缓冲区大小。

      1. dst_bufsize = av_samples_get_buffer_size(&dst_linesize, DST_CHANNELS,
          			frame_count, DST_SAMPLE_FMT, 0);
        if (dst_bufsize < 0) {
          	av_freep(&buffer);
          	printf("av_samples_get_buffer_size error\n");
          	return -1;
         }
        
    7. 写入 wav 文件

      1. audioFileSize += dst_bufsize;
        fwrite(buffer, 1, dst_bufsize, p);
        fflush(p);
        av_freep(&buffer);
        
    8. 写入文件长度和数据长度 ,最后关闭文件

      1. fseek(p, 40, SEEK_SET);
        fwrite(&audioFileSize, 1, sizeof(int32_t), p);
        audioFileSize += 36;
        fseek(p, 4, SEEK_SET);
        fwrite(&audioFileSize, 1, sizeof(int32_t), p);
        fclose(p);
        

DEMO: https://download.csdn.net/download/haiyangyunbao813/17984367


参考博客 🅱️​

  1. https://blog.csdn.net/weixin_41353840/article/details/112568105?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase
  2. https://blog.csdn.net/sun007700/article/details/115034806

在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值