【问题标题】:Extract AUDIO, manipulate & merge again提取音频,再次操作和合并
【发布时间】:2023-03-09 02:57:02
【问题描述】:

我正在使用 Spleeter 从音频中删除音乐。

我的目标是构建一个脚本,使从视频中提取音频的过程自动化,对提取的音频执行 Spleeter,然后将经过处理的音频合并回视频中,替换原始音频。

我遇到的主要问题是我没有足够的内存来处理整个提取的音频。我需要将其拆分为多个部分并在每个部分上执行 Spleeter。

然后将处理后的片段连接在一起,并将结果合并到视频中。

这是我尝试过的:

#!/bin/bash

cd ~/Desktop/Video-convert

# create audio from video
ffmpeg -i *.mp4 output.mp3

# Split the audio into pieces
ffmpeg -i output.mp3 -f segment -segment_time 120 -c copy output_%03d.mp3


# Execute Spleeter upon each sample
FILES=~/Desktop/Video-convert/*.mp3

for f in $FILES
do
  spleeter separate -i $f -o output_vocal
done

# delete unneeded audios
rm *.mp3
cd output_vocal

# ===========================================================
# the problem starts here
# ===========================================================

# concatenate manipulated audios together
find . -name 'vocals.wav' -exec echo {} >> mylist.txt \;

ffmpeg -f concat -safe 0 -i mylist.txt -c copy vocal.mp3

mv vocal.mp3 ../

cd ../

# merge the audio back to video
ffmpeg -i *.mp4 -i vocal.mp3 \
-c:v copy -c:a aac -strict experimental \
-map 0:v:0 -map 1:a:0 vocal-vid.mp4

在必须将音频连接在一起之前,一切都运行良好。 Spleeter 将结果输出到 vocal.wavaccompaniment.wav 中的子文件夹中,该子文件夹的名称与已处理的音频相同。

文件树如下所示:

output_vocal
- output_000
----- vocal.wav
----- accompaniment.wav
- output_001
----- vocal.wav
----- accompaniment.wav
- output_002
----- vocal.wav
----- accompaniment.wav

如您所见,问题在于命名。我的目标是将所有 vocal.wav 连接成一个 mp3 音频。

然后将最终的 vocal.mp3 音频与 *.mp4 视频合并。

唯一的问题是 Spleeter 输出结果音频的方式。

【问题讨论】:

  • 那么问题出在哪里?只是拼写错误“vocals.wav”与“vocal.wav”吗?
  • 即使修正了错字,它也不起作用。音频没有连接在一起。 mylist.txt 为空。
  • 出了点问题:[ find . -name 'vocals.wav' -exec echo {} >> mylist.txt \; ] 我的错误是最终的vocal.mp3 不存在无法弄清楚如何将音频连接到一个vocal.mp3 中。
  • find 命令不进行任何连接,但它会创建一个文件列表(并将其放入另一个文件“mylist.txt”中)。如果“mylist.txt”的内容是您所期望的,那么这个 cmd 确实有效。否则我们需要在你运行它之后知道它包含什么。

标签: linux bash shell audio ffmpeg


【解决方案1】:

您遇到的问题是 ffmpeg 的 concat demuxer 需要一个包含指令的输入文件,而不是一个简单的文件列表。

您的find 调用会创建一个文件,例如:

output_vocal/output_000/vocal.wav
output_vocal/output_001/vocal.wav
output_vocal/output_002/vocal.wav

而 ffmpeg 的 concat demuxer 确实需要这样的文件:

file output_vocal/output_000/vocal.wav
file output_vocal/output_001/vocal.wav
file output_vocal/output_002/vocal.wav

另请注意,find 不一定按字母顺序返回文件,而您很可能希望按该顺序连接文件。

最后,在连接 WAV 文件时,不能使用 copy 编解码器生成 MP3 文件(因为 WAV/RIFF 编解码器不是 MP3)。但无论如何您都不需要中间 MP3 文件

这是一个更新的脚本, - 为所有中间文件使用临时目录 - 遍历 cmdline 提供的所有 mp4 文件(而不是硬编码输入目录) - 为每个输入文件“XXX.mp4”创建一个“XXX_voc.mp4”文件(覆盖任何现有文件)

#!/bin/bash

for infile in "$@"
do
  outfile=${infile%.mp4}_voc.mp4

  # create a temp-directory to put our stuff to
  TMPDIR=$(mktemp -d)

  # create audio from video
  ffmpeg -i "${infile}" "${TMPDIR}/output.mp3"

  # Split the audio into pieces
  ffmpeg -i "${TMPDIR}/output.mp3" -f segment -segment_time 120 -c copy "${TMPDIR}/output_%03d.mp3"

  # Execute Spleeter upon each sample
  find "${TMPDIR}" -maxdepth 1 -type f -name "output_*.mp3" \
    -exec spleeter separate -i {} -o "${TMPDIR}/output_vocal" ";"

  # find all 'vocal.wav' files generated by spleeter, sort them, 
  # prefix them with 'file ', and put them into output.txt
  find "${TMPDIR}/output_vocal" -type f -name "vocal.wav" -print0 \
  | sort -z \
  | xargs -0 -I{} echo "file '{}'" \
  > "${TMPDIR}/output.txt"
  # concatenate the files and create an MP3 file
  ffmpeg -f concat -safe 0 -i "${TMPDIR}/output.txt" -c copy "${TMPDIR}/vocal.wav"

  # merge the audio back to video
  ffmpeg -y -i "${infile}" -i "${TMPDIR}/vocal.wav" \
    -c:v copy -c:a aac -strict experimental \
    -map 0:v:0 -map 1:a:0 "${outfile}"

  rm -rf "${TMPDIR}"
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多