77 lines
2.2 KiB
Python
77 lines
2.2 KiB
Python
"""
|
||
NovaAi – TTS-Engine-Hub
|
||
utils/audio.py
|
||
Version: v0.0.1
|
||
|
||
Description:
|
||
Audio processing utilities: concat, merging chunks, etc.
|
||
|
||
Author: Abby (ChatGPT)
|
||
Date: 2025-07-23
|
||
Canvas: utils/audio.py
|
||
"""
|
||
|
||
import tempfile
|
||
import os
|
||
import ffmpeg
|
||
import shutil
|
||
|
||
def check_ffmpeg():
|
||
"""Check if ffmpeg is installed and available in the system's PATH."""
|
||
return shutil.which("ffmpeg") is not None
|
||
|
||
def concat_audio(files, fmt):
|
||
"""
|
||
Concatenate a list of audio files into a single file of the given format.
|
||
Supports: wav, ogg, mp3
|
||
"""
|
||
if len(files) == 1:
|
||
# If there's only one file, just return it, no cleanup needed here.
|
||
return files[0]
|
||
|
||
# Securely create a temporary file for the output
|
||
with tempfile.NamedTemporaryFile(suffix=f'.{fmt}', prefix="chunked_", delete=False) as temp_output_file:
|
||
output_file_path = temp_output_file.name
|
||
|
||
try:
|
||
if fmt == "wav":
|
||
import wave
|
||
data = []
|
||
params = None
|
||
for f in files:
|
||
with wave.open(f, 'rb') as wf:
|
||
if params is None:
|
||
params = wf.getparams()
|
||
data.append(wf.readframes(wf.getnframes()))
|
||
with wave.open(output_file_path, 'wb') as wf:
|
||
wf.setparams(params)
|
||
for d in data:
|
||
wf.writeframes(d)
|
||
else:
|
||
if not check_ffmpeg():
|
||
raise RuntimeError("ffmpeg not found. Please install ffmpeg and ensure it is in your PATH.")
|
||
|
||
with tempfile.NamedTemporaryFile("w", delete=False) as tf:
|
||
list_file_path = tf.name
|
||
for f in files:
|
||
tf.write(f"file '{os.path.abspath(f)}'\\n")
|
||
tf.flush()
|
||
|
||
try:
|
||
(
|
||
ffmpeg
|
||
.input(list_file_path, format='concat', safe=0)
|
||
.output(output_file_path, acodec='copy')
|
||
.run(overwrite_output=True, quiet=True)
|
||
)
|
||
finally:
|
||
os.unlink(list_file_path)
|
||
|
||
finally:
|
||
# Clean up the input chunk files
|
||
for f in files:
|
||
if os.path.exists(f):
|
||
os.remove(f)
|
||
|
||
return output_file_path
|