我有两个音频轨道,从两个视频中提取。
它们听起来几乎一样,除了一些区别。
我想知道是否有任何解决方案可以使这两条路线保持一致。
这是我到目前为止尝试过的:
我会尝试消除两个音频中每个场景之间的静音间隔,以便您仅获得每个场景的一对干净音频片段列表。
然后我将重新创建两个音频信号。拉伸的信号在每个场景之间将具有恒定长度的间隙。原始(未拉伸)信号在场景之间具有可变的间隙,等于[length of constant gap] + [length of stretched scene - length of normal scene]
。这将使每个场景都在同一时间开始。
如果场景之间的间隙将音频信号降低到理想的零电平,则检测和消除间隙应该很简单。
否则,这可能会有些棘手(通常会有一些DC偏移和/或某些背景噪声信号,使得从时域波表示中检测“静音”有点困难)。之前,我已成功使用声能计算来精确检测音频信号的开始/结束位置。这意味着沿着音频滑动傅立叶变换(确保使用带有Hann或Hamming窗口的锥形变换)。获得变换结果后,就可以通过执行以下计算来计算能量:
E = Sum(r[x]*r[x] + i[x]*i[x])
x从0到[傅立叶变换的长度] / 2-1,其中r代表每个结果仓的实部,而i代表每个结果仓的虚部。
此计算在沿音频滑动傅立叶变换的同时重复记录,同时沿途记录能量。 通过适当的阈值处理,您可能可以成功隔离每个场景的音频部分。
傅立叶变换的长度可以很小(可能在64-256范围内就足够了,因为您不希望有很好的频率分辨率,只需估算某个时间点上存在的总能量即可)
这是一个锥形傅立叶变换调用(using the fftw3 library)的示例,用于计算频带范围内的能量:
double EnergyAnalyzer::GetEnergy(array<double>^ audioFrame, Int32 startIndex) {
if( startIndex + FrameSize > audioFrame->Length ) {
throw gcnew ArgumentException("The value of startIndex would overflow the array's boundary", "startIndex");
}
// Prepare input to the fourier transform. The signal is tapered using a Hann window
for( int i = 0; i < FrameSize; i++ ) {
_pIn[i] = audioFrame[startIndex + i] * _hann[i];
}
fftw_execute(_fftPlan);
double energy = 0.0;
for( int i = _binStart; i <= _binStop; i++ ) {
energy += _pOut[i][0] * _pOut[i][0] + _pOut[i][1] * _pOut[i][1];
}
return energy;
}
Dynamic Time Warping(DTW)是用于对齐长度/速度可能略有不同的数据序列的规范算法。 Python库librosa有使用它的简短教程for music syncronization。
[某些图形音频编辑器中也可能有DTW实现,但我不熟悉。