通过声音频率判断歌手是否假唱 B站码农高天视频内容复现

该文介绍了如何利用ffmpeg裁剪音频片段,spleeter消除背景音,以及parselmouth分析频率来检测假唱的方法。通过这段代码,可以对跨年演唱会的歌手音频进行分析,识别出人声和伴奏,并对人声频率进行详细分析,以判断是否为真唱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

王俊凯真nb


假唱

原视频链接(bilibili):
一眼就能看出唱功和假唱?用软件来分析一下跨年演唱会的歌手们!

1. 使用ffmpeg裁剪音频片段

没有ffmpeg,用pr等剪辑软件也可以

ffmpeg -ss 0:30 -i input.wav -t 15 out.wav

代表将input.wav,从00:30开始,截取15s片段,输出到out.wav
只是用来做频率分析的话,编码,采样率等参数不太重要,保持默认即可

2. 使用spleeter消除背景音

安装细节自行百度,装不上或者跑不起来的话,用网上其他平台也能实现消除背景音

github地址:https://github.com/deezer/spleeter
安装直接使用pip即可(python3.11不支持,需要3.10及以下):

pip install spleeter

使用:

python -m spleeter separate 'pm.mp3' -p spleeter:2stems -o 'output' --verbose

建议使用绝对路径

输出在output\<音频名>,其中vocals.wav是人声,accompaniment.wav是伴奏
在这里插入图片描述

3. 使用parselmouth分析频率

脚本在末尾
基于github上给的代码和天哥视频中放出的代码,经过我修饰的


tone = 'E'

代表当前歌曲的调子
在这里插入图片描述

此为 E 调

snd = parselmouth.Sound(r"output\pm\vocals.wav")

调整输入音频文件,这里传入的参数是经过上两步处理后的音频文件。
1
这是《泡沫》的前两句的频率图,对比简谱图(只能看懂简朴图了)
1
这是QQ音乐上下载的歌,自然是修过的,音准极好。


4. 完整代码

import parselmouth
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from itertools import product
from matplotlib import rcParams
from matplotlib.ticker import MultipleLocator
config = {
    "font.family":'serif',
    "font.size": 8,
    "mathtext.fontset":'stix',
    "font.serif": ['SimSun'],
}
sns.set()
rcParams.update(config)

tone = 'E'

class Tonality:
    base_diff = [0,2,4,5,7,9,11]
    tones = ['A','A#','B','C','C#','D','D#','E','F','F#','G','G#']
    def __init__(self,tone):
        assert (tone.upper() in self.tones) or (tone[::-1].upper() in self.tones)
        self.base_freq = self.tone_to_freq(tone)

    def tone_to_freq(self,tone):
        A_freq = 440
        return A_freq * (2**(self.tones.index(tone)/12))

    def get_freq(self):
        ret = []
        for r in range(-3,2):
            base = self.base_freq * (2**r)
            ret.extend([base * (2**(diff/12)) for diff in self.base_diff])
        return ret


# snd = parselmouth.Sound("output\\pm\\vocals.wav")
snd = parselmouth.Sound(r"pm_.wav")
pitch = snd.to_pitch()
plt.figure(figsize=(15,8),dpi=144)

y_ticks_v = Tonality(tone).get_freq()
stage = ['low-low ','low ','midium ','high ','high-high ']
stage = ['降降 ','降','中','升','升升']
basePitch = ['1','1#','2','2#','3','4','4#','5','5#','6','6#','7']
basePitch = list('1234567')

y_ticks = [''.join(i) for i in product(stage,basePitch)]
y_ticks = [i+" - %6.2f"%(j) for i,j in zip(y_ticks,y_ticks_v)]
plt.yticks(y_ticks_v,y_ticks)

pitch_values = pitch.selected_array['frequency']
pitch_values[pitch_values==0] = np.nan
plt.plot(pitch.xs(), pitch_values, 'o', markersize=3, color='w')
plt.plot(pitch.xs(), pitch_values, 'o', markersize=1.5)

plt.ylim(0, pitch.ceiling)
plt.ylabel("fundamental frequency [Hz]")
plt.xlabel('Time [s]')
plt.xlim([snd.xmin, snd.xmax])

ax = plt.gca()
# plt.grid(ls='-',color='blue')
ax.xaxis.set_major_locator(MultipleLocator(5));
ax.xaxis.grid(color='blue',ls=':',lw=1,alpha=0.3)
ax.yaxis.grid(color='blue',ls='-',lw=1,alpha=0.6)

plt.savefig("pitch.png")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值