首页 > 其他分享 >FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频

FFmpeg开发笔记(五十八)把32位采样的MP3转换为16位的PCM音频

时间:2024-10-19 12:42:44浏览次数:1  
标签:采样 FFmpeg 16 32 音频 PCM pcm

​《FFmpeg开发实战:从零基础到短视频上线》一书的“5.1.2  把音频流保存为PCM文件”介绍了如何把媒体文件中的音频流转存为原始的PCM音频,在样例代码的转存过程中,解码后的PCM数据未经任何加工处理,就直接保存到二进制文件。也就是说,原音频的采样频率是多少,PCM文件的采样频率也是多少;原音频的声道数量是多少,PCM文件的声道数量也是多少;原音频的采样位数是多少,PCM文件的采样位数也是多少。

原汁原味保存的PCM文件本来也没什么问题,可是在实际应用中,有的业务场景需要特定规格的PCM音频。比如某厂家的语音识别引擎,要求只能输入16位的PCM数据,然而标准的MP3音频都采用32位采样,如此一来,得想办法把32位的MP3音频转换为16位的PCM音频才行。
考虑到使用FFmpeg的命令行转换比较方便,于是在控制台执行下面的ffmpeg格式转换指令,在转换采样频率和声道数量的同时一起转换采样位数。

ffmpeg -i night.mp3 -ar 16000 -ac 1 -acodec pcm_s16le night.pcm

谁知控制台输出以下的报错信息“pcm_s16le codec not supported”,意思是不支持16位的PCM编码器。

pcm_s16le codec not supported

咦,FFmpeg怎么会不支持这么基本的PCM编码器呢?继续执行下面的编码器查看命令:

ffmpeg -encoders | grep pcm

发现输出的查询结果赫然出现下面的pcm_s16le信息,说明FFmpeg默认已经支持该编码器。

A....D pcm_s16le            PCM signed 16-bit little-endian

那么为啥ffmpeg命令行无法正常转换PCM音频的采样位数呢?
搜了一圈发现没有使用ffmpeg成功转换采样位数的案例,只好先把原音频转换为32位采样的PCM文件,转换命令如下所示:

ffmpeg -i night.mp3 -ar 16000 -ac 1 -acodec pcm_f32le -f f32le night.pcm

接下来另外编写转换音频采样位数的代码convertpcm.c,代码内容如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int pcm32_to_pcm16(const char *filename)
{  
    FILE *fp =  fopen(filename, "rb");
    FILE *fp1 = fopen("output_16.pcm", "wb");
    unsigned char *sample = (unsigned char*)calloc(1, 4+1);
    while(!feof(fp))
    {
        fread(sample, 4, 1, fp);
        sample[4] = '\0';
        float *sample32 = (float*)sample;
        short sample16 = (short)floor( (*sample32) * 32767 );
        fwrite(&sample16, 2, 1, fp1);
    }
    free(sample);
    fclose(fp);
    fclose(fp1);
    return 0;  
}

int main(int argc, char **argv) {
    const char *src_name = "night.pcm";
    if (argc > 1) {
        src_name = argv[1];
    }
    pcm32_to_pcm16(src_name);
}

保存代码,然后执行下面的编译命令。

gcc convertpcm.c -o convertpcm 

编译完成,再执行下面的采样位数转换命令。

./convertpcm night.pcm

现在生成的output_16.pcm就是16位采样的PCM文件,可以用作语音识别了。

更多详细的FFmpeg开发知识参见《FFmpeg开发实战:从零基础到短视频上线》一书。

标签:采样,FFmpeg,16,32,音频,PCM,pcm
From: https://www.cnblogs.com/aqi00/p/18450146

相关文章

  • 【TFT彩屏移植】STM32F4移植1.8寸TFT彩屏简明教程
    目录一.移植说明二.移植1.例程    物理接口:    延时函数:     底层驱动文件:    GUI界面文件:    测试demo:2.移植至F4创建工程:        调试接口选择SW:        RCC中HSE选择外部晶振:        GPIO配......
  • ctfshow(29->32)--RCE/命令执行漏洞
    Web29源代码:error_reporting(0);if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/flag/i",$c)){eval($c);}}else{highlight_file(__FILE__);}代码审计:error_reporting(0)关闭所有php报错。preg_matc......
  • stm32是世界上最简单的
    例一include"stm32f10x.h"include"generic.h"//1.打开时钟2.配置3.初始化例子:点gpioa的第一个灯voidpin_init(GPIO_TypeDef*GPIOx,,uint16_tGPIO_Pin,GPIOMode_TypeDefGPIO_Mode){//直接调用这个函数if(GPIOx=GPIOA)RCC_APB2PeriphClockCdm(RCC_APB2Perph_GPIO......
  • int32_t的发散性问题
    int32_t 是一个在C和C++中定义的固定宽度整数类型。它表示一个32位的有符号整数类型,定义在 stdint.h(C标准库)或 cstdint(C++标准库)中。宽度:32位取值范围:-2,147,483,648到2,147,483,647类型:有符号整数(signed),即可以表示正数、负数和零。这种类型确保了在......
  • XC6SLX25T-2CSG324C,XC6SLX45T-2FGG484I,XC7K70T-3FBG484E4914, XILINX/赛灵思 嵌入式
    Xilinx是一家总部位于美国的半导体公司,成立于1984年。他们的主要产品是可编程逻辑器件(FPGA和SoC)和相关的开发工具。Xilinx的FPGA产品被广泛应用于各种领域,包括通信、数据中心、工业控制、汽车、物联网等。他们的产品具有灵活性高、性能强大和可定制性强等特点。2018年,Xilinx宣......
  • [CF1616H] - Keep XOR Low 的题解
    一道比较神奇的题目,状态显得比较扯淡,但是就是能过!先建立出trie树,设\(dp_u\)表示以\(u\)为根的子树内的答案。但我们发现,若\(x\)的当前位为\(1\),那么问题就没法根据他的左右子树求解了,怎么办呢。考虑一个很扯淡的状态,设\(dp_{u,v}\)表示考虑了\(u,v\)为根的子树,他......
  • day16
    IO流IO流【输入输出流】:按照流向划分:输入流:外部数据->java程序输出流:java程序->外部数据按照数据类型划分【根据使用记事本打开是否能够看懂来决定】:字节流【万能流】:字节输出流:......
  • GhostDoc Enterprise.v2024.1.24160 for Visual Studio 2022插件漏洞分析和离线解锁方
      先安装,然后直接使用dnspy调试VisualStudio2022,以GhostdocPro的注册对话框作为突破口进行调试。经过一些调试可以比较轻松的发现关键点在SubMain.GhostDoc.Services.clr4.dll中,你可以通过everything在vs的插件目录中找到这个dll所在位置,其它版本的VisualStudio的方法是类似......
  • java_day16_IO、序列化
    一、IO流IO流划分IO流【输入输出流】:按照流向划分:输入流:外部数据->java程序输出流:java程序->外部数据按照数据类型划分【根据使用记事本打开是否能够看懂来决定】字节流【万能流】:字节输入流:InputStream【抽象类】-......
  • 《ESP32从0到1》收官篇:wifi版温湿度蓝牙网关
            文章内容:以“wifi版温湿度蓝牙网关”这一具体项目为载体,对《ESP32从0到1》专辑前面所有内容的整合练习。        本篇设定为VIP可见,未开通VIP的可移至如下链接,每个组件功能之前均有单独发布,且涉及到的源码也已上传,可自行下载。《ESP32从0到1》快速......