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

embedded/2024/10/21 6:00:52/

《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进阶文章目录为《FFmpeg开发笔记全目录(FFmpeg开发实战详解,含直播系统的搭建过程)》


http://www.ppmy.cn/embedded/118114.html

相关文章

伊犁-linux 硬盘添加,分区,格式化

主要是linux 下操作硬盘分区&#xff0c;格式化 这样1个sata 盘就添加成功了 &#xff01;  继续添加三块 sata1 hda sata hdb sata hdc sata hdd scsi sda 作为启动盘 进行操作系统的引导 如果scsi 往下调整 先敲enter 在用&#xff0d; 号往下 如果是往上调整敲…

python 2024-10

第七课 204. 计数质数 语法&#xff1a;while else&#xff0c;continue break 埃氏筛 数的倍数不是素数。 class Solution:def countPrimes(self, n: int) -> int:res 0for i in range(2, n):for j in range(2, i):if i % j 0:breakelse:res 1return res优化 class …

python 实现random forest regressor随机森林回归器算法

random forest regressor随机森林回归器算法介绍 随机森林回归器&#xff08;Random Forest Regressor&#xff09;是一种基于决策树的集成学习算法&#xff0c;用于回归任务。它是随机森林算法在回归问题上的应用。随机森林通过构建多个决策树并将它们的预测结果进行汇总来提…

【小沐学CAD】3ds Max常见操作汇总

文章目录 1、简介2、二次开发2.1 C 和 3ds Max C SDK2.2 NET 和 3ds Max .NET API2.3 3ds Max 中的 Python 脚本2.4 3ds Max 中的 MAXScript 脚本 3、快捷键3.1 3Dmax键快捷键命令——按字母排序3.2 3dmax快捷键命令——数字键3.3 3dmax功能键快捷键命令3.4 3Dmax常用快捷键——…

c++实现TCPUDP

做网络通信作业之前的学习 !(>。<)! 一.TCP 1.服务端流程 1.创建socket套接字 socket套接字可以理解成网络接口&#xff0c;只有通过了socket套接字才能跟对应的电脑进行通信 2.给这个socket绑定一个端口号 IP地址是指定电脑的 端口号是指定电脑上面某个软件的 3.给soc…

mxnet同步机制

mxnet同步机制 在 MXNet 中&#xff0c;多个算子和多个内核&#xff08;kernel&#xff09;的同步机制依赖于 CUDA 流&#xff08;CUDA Streams&#xff09; 和 事件&#xff08;CUDA Events&#xff09;&#xff0c;以及其内部的 执行引擎&#xff08;Execution Engine&#…

AI 赋能大模型:从 ChatGPT 到国产大模型的角逐与发展契机

在当今科技飞速发展的时代&#xff0c;大模型作为人工智能领域的关键技术&#xff0c;正引发着深刻的变革。它们在自然语言处理、计算机视觉、语音识别等众多领域展现出了惊人的潜力&#xff0c;为各行各业带来了前所未有的机遇和挑战。本文将深入剖析大模型的技术原理、市场态…

25届秋招总结——保持自信、坚定选择

前言 好久不见&#xff01;博主已经快三个月没有更新啦&#xff0c;因为这三月一直在经历秋招&#xff0c;很幸运最后在国庆节前结束了秋招&#xff0c;可以回去好好过节喽&#xff0c;这里也简单和各位小伙伴分享一下我的秋招总结吧&#xff0c;希望也可以帮助到一些小伙伴&a…