FFMPEG / Разделить, а потом склеить
У меня есть длинный аудио-файл, мне надо разбить его на меньшие куски. Я делаю это с помощью FFMPEG. Разделение происходит в месте пауз длинной не менее 1,5 секунды. И с этим проблем нет. Проблема начинается потом — по какой-то странной причине, совокупная длина всех отрезков, созданных из длинного файла — не соответствую продолжительности (длине) этого самого исходного файла. Где я ошибся?
Прилагаю код, с которым я работаю:
import subprocess
import os
from pydub import AudioSegment
# Путь к исходному WAV-файлу и каталогу для выходных файлов
input_wav_file = "/content/drive/MyDrive/RVC/Audios/pinochet/Pinochet.wav"
cut_wav_dir = "/content/drive/MyDrive/RVC/Audios/pinochet/cut"
# Убедитесь, что каталог для выходных файлов существует
os.makedirs(cut_wav_dir, exist_ok=True)
# Загрузка аудиофайла
audio = AudioSegment.from_wav(input_wav_file)
# Настройка параметров для обнаружения тишины
min_silence_duration = 1.5 # Минимальная продолжительность тишины между фрагментами в секундах
# Команда для разделения аудиофайла на фрагменты с помощью FFMPEG
ffmpeg_command = [
"ffmpeg",
"-i", input_wav_file,
"-af", f"silencedetect=noise=-30dB:d={min_silence_duration}",
"-f", "null", "-"
]
# Выполнение команды FFMPEG и захват вывода
print("Выполняется анализ аудиофайла на наличие тишины...")
output = subprocess.check_output(ffmpeg_command, stderr=subprocess.STDOUT).decode()
print("Анализ завершен.")
# Извлечение временных меток тишины из вывода
silence_timestamps = [float(line.split()[4]) for line in output.splitlines() if "silence_start" in line]
# Разделение аудиофайла на фрагменты с помощью FFMPEG и временных меток тишины
print("Выполняется разделение аудиофайла на фрагменты...")
for i, timestamp in enumerate(silence_timestamps):
start_time = timestamp
end_time = silence_timestamps[i + 1] if i + 1 < len(silence_timestamps) else None
output_file = os.path.join(cut_wav_dir, f"chunk{i:03d}.wav")
ffmpeg_split_command = [
"ffmpeg",
"-i", input_wav_file,
"-ss", str(start_time),
"-to", str(end_time) if end_time is not None else "",
"-acodec", "copy",
output_file
]
print(f"Экспорт фрагмента {i + 1}/{len(silence_timestamps)}...")
subprocess.run(ffmpeg_split_command)
print("Разделение завершено.")
# Вывод информации о длине исходного файла и совокупной длине всех файлов-отрезков
print(f"Длина исходного файла: {len(audio) / 1000} секунд")
total_duration_chunks = sum(end_time - start_time for start_time, end_time in zip(silence_timestamps, silence_timestamps[1:]))
print(f"Совокупная длина всех файлов-отрезков: {total_duration_chunks} секунд")
# Проверка соответствия длины исходного файла совокупной длине всех файлов-отрезков
if total_duration_chunks != len(audio) / 1000:
print("Внимание: совокупная длина всех файлов-отрезков не соответствует длине исходного файла.")
else:
print("Совокупная длина всех файлов-отрезков соответствует длине исходного файла.")
Ответы (1 шт):
Автор решения: Dmitry Aleshkovskiy
→ Ссылка
Решилось все c использованием split_on_silence и параметром keep_silence=True:
from pydub import AudioSegment
from pydub.silence import split_on_silence
import os
def split_audio(input_file, output_folder):
# Загрузка аудиофайла
if input_file.lower().endswith('.wav'):
audio = AudioSegment.from_wav(input_file)
elif input_file.lower().endswith('.mp3'):
audio = AudioSegment.from_mp3(input_file)
else:
raise ValueError("Unsupported file format. Please use WAV or MP3.")
# Разделение на фрагменты
chunks = split_on_silence(audio, min_silence_len=1000, silence_thresh=audio.dBFS-14, keep_silence=True)
# Создание папки для вывода, если она еще не существует
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# Экспорт фрагментов
total_length = 0
for i, chunk in enumerate(chunks):
chunk_file = os.path.join(output_folder, f"chunk{i}.mp3")
chunk.export(chunk_file, format="mp3")
total_length += len(chunk)
# Проверка соответствия длительности
original_length = len(audio)
if original_length == total_length:
print("Успех: Суммарная длительность фрагментов соответствует длительности исходного файла.")
else:
print("Предупреждение: Суммарная длительность фрагментов не соответствует длительности исходного файла.")
split_audio('path/to/your/audiofile.mp3', 'path/to/output/folder')