audio - 如何使用 FFmpeg 获得音频峰值?

标签 audio ffmpeg waveform spectrum audiowaveform

我正在开发一款音乐应用,需要为我的文件生成音频频谱。就像这个:

enter image description here

所以我尝试使用 audiowaveform像这样:

audiowaveform -i music.mp3 --pixels-per-second 1 -o out.dat

这给了我以下结果[正确结果]:[前 10 个词是元数据]

0000000 0001 0000 0000 0000 bb80 0000 bb80 0000
0000020 00f9 0000 df3e 1fa2 e22c 1ef3 e0bb 1e5a
0000040 e099 1e88 dfcf 1c33 e29f 1d4c e055 1f80
0000060 df63 1e3a e1b4 1f31 e271 1d81 e0e5 1b1c
0000100 e06d 1be4 dee2 1cb0 e118 1da1 e026 1dea
0000120 e055 1dac df9b 1dbf e0c3 2063 ded4 21b2
0000140 dec9 1f8d de5b 20c8 e02d 216a dd7e 21af
0000160 dea1 20ac de6c 2170 de80 1e12 de6f 1fb9
0000200 dde3 2106 e0d9 21be de88 218c de81 1f9f
0000220 decb 20ff deb2 1edc df32 20c4 dde7 ...

但是当我用 FFmpeg 做这种工作时:

ffmpeg -y -i music.mp3 -acodec pcm_s16le -f s16le -ac 1 -ar 1 -v quiet out.pcm

这给出了以下结果,完全不同:

0000000 0001 fffe fffe fffe 0000 ffff fffd 0000
0000020 ffff ffff fffe 0001 0001 fffd 0001 fffe
0000040 0002 fffe fffc 0002 ffff fffc fffe 000b
0000060 0007 fffb 0004 0001 ffff fffd ffff 0002
0000100 0008 0006 fffe ffff 0001 0000 0003 000a
0000120 fffd ffff 0004 ffff 0001 ffff fffd ffff
0000140 fffe ffff 0001 fffd fffe 0000 fffb 0002
0000160 0002 0000 fffe 0000 fffb fffe fffe 0000
0000200 ffff 0000 ffff fffc 0002 0003 0005 0003
0000220 0002 fffb fffb fffa fffa 0004 0009 ...

您可能想知道为什么我要执行 -ar 1--pixels-per-second 1?这是因为我要为每一秒画一条线,所以我需要每一秒都得到峰值。 .我不知道我在那里错过了什么,但我希望从 FFmpeg 得到相同的结果。

最佳答案

这不是 FFMPEG 的解决方案,但仍会产生波形阵列。

我的解决方案是使用 audiowaveform linux 软件包,它有一个简单的 cli,可以以所需的采样率提取波形数据。

你可以像这样在 ubuntu 上安装它:

sudo add-apt-repository ppa:chris-needham/ppa
sudo apt-get update
sudo apt-get install audiowaveform

或在 macOS 上使用 homebrew喜欢:

brew tap bbc/audiowaveform
brew install audiowaveform

首先,我使用问题中提供的命令绘制波形,但它不准确且脏。因为它每秒取一个样本,这不是我想要的。所以我决定每秒取 100 个样本,然后用一些 JS 代码得到平均值。所以提取波形的命令将是:

audiowaveform -i /root/audio.mp3 --pixels-per-second 100 --output-format json -

这将在标准输出上输出音频波形数据和一些元数据(末尾的连字符起到了作用)。所以在我的例子中,我使用 NodeJs 来获得这个输出并将波形数组减少到波形 block 的平均值。 请注意,我从波形中删除了负数以处理波形的上半部分。

import {exec} from "child_process";

export default function getAudioWaveform(filename, blockSize = 100) {
    return new Promise((resolve, reject) => {
        const command = `audiowaveform -i ${filename} --pixels-per-second ${blockSize} --output-format json -`;

        exec(command, (error, stdout, stderr) => {
            if (error) reject(error, stderr);

            try {
                const data = JSON.parse(stdout).data.filter((_, i) => i % 2 === 1)

                const waveform = [];
                for (let i = 0; i < data.length; i++)
                    waveform[i] = Math.round(data.slice(i * 100, (i + 1) * 100).reduce((s, n) => s + n, 0) / 100);

                resolve(waveform);
            } catch (ex) {
                reject(ex);
            }
        });
    })
}

关于audio - 如何使用 FFmpeg 获得音频峰值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62242044/

相关文章:

javascript - 不同按钮上的音频播放/暂停单击 Jquery

ffmpeg - 转换为 HLS VS MPEGTS

ffmpeg - 如何从 HEVC 比特流中删除帧?

html - 如何在html5中绘制音频流的波形?

audio - Pyglet:控制音频平衡(平移)

iphone - 如何在录制时将背景音频静音(使用音频队列服务)

javascript - 这是哪种音频频谱分析仪?

ffmpeg - 使用 FFMPEG 缩小视频尺寸 - 设置最大宽度和高度

c++ - 如何为 qwt 示波器示例生成方波?

java - 从 32 位样本大小的 WAV 创建样本数组