2024-12-31 01:52:16 -07:00
|
|
|
"""Audio conversion service"""
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
from io import BytesIO
|
2024-12-31 02:55:51 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
import numpy as np
|
|
|
|
import soundfile as sf
|
2024-12-31 02:55:51 -07:00
|
|
|
import scipy.io.wavfile as wavfile
|
|
|
|
from loguru import logger
|
2024-12-31 01:52:16 -07:00
|
|
|
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
class AudioService:
|
|
|
|
"""Service for audio format conversions"""
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
@staticmethod
|
2024-12-31 01:57:00 -07:00
|
|
|
def convert_audio(
|
|
|
|
audio_data: np.ndarray, sample_rate: int, output_format: str
|
|
|
|
) -> bytes:
|
2024-12-31 01:52:16 -07:00
|
|
|
"""Convert audio data to specified format
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
Args:
|
|
|
|
audio_data: Numpy array of audio samples
|
|
|
|
sample_rate: Sample rate of the audio
|
|
|
|
output_format: Target format (wav, mp3, etc.)
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
Returns:
|
|
|
|
Bytes of the converted audio
|
|
|
|
"""
|
|
|
|
buffer = BytesIO()
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
try:
|
2024-12-31 01:57:00 -07:00
|
|
|
if output_format == "wav":
|
2024-12-31 01:52:16 -07:00
|
|
|
logger.info("Writing to WAV format...")
|
|
|
|
wavfile.write(buffer, sample_rate, audio_data)
|
|
|
|
return buffer.getvalue()
|
2024-12-31 01:57:00 -07:00
|
|
|
|
|
|
|
elif output_format == "mp3":
|
2024-12-31 01:52:16 -07:00
|
|
|
# For MP3, we need to convert to WAV first
|
|
|
|
logger.info("Converting to MP3 format...")
|
|
|
|
wav_buffer = BytesIO()
|
|
|
|
wavfile.write(wav_buffer, sample_rate, audio_data)
|
|
|
|
wav_buffer.seek(0)
|
2024-12-31 01:57:00 -07:00
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
# Convert WAV to MP3 using soundfile
|
|
|
|
buffer = BytesIO()
|
2024-12-31 01:57:00 -07:00
|
|
|
sf.write(buffer, audio_data, sample_rate, format="mp3")
|
2024-12-31 01:52:16 -07:00
|
|
|
return buffer.getvalue()
|
2024-12-31 01:57:00 -07:00
|
|
|
|
|
|
|
elif output_format == "opus":
|
2024-12-31 01:52:16 -07:00
|
|
|
logger.info("Converting to Opus format...")
|
2024-12-31 01:57:00 -07:00
|
|
|
sf.write(buffer, audio_data, sample_rate, format="ogg", subtype="opus")
|
2024-12-31 01:52:16 -07:00
|
|
|
return buffer.getvalue()
|
2024-12-31 01:57:00 -07:00
|
|
|
|
|
|
|
elif output_format == "flac":
|
2024-12-31 01:52:16 -07:00
|
|
|
logger.info("Converting to FLAC format...")
|
2024-12-31 01:57:00 -07:00
|
|
|
sf.write(buffer, audio_data, sample_rate, format="flac")
|
2024-12-31 01:52:16 -07:00
|
|
|
return buffer.getvalue()
|
2024-12-31 01:57:00 -07:00
|
|
|
|
|
|
|
elif output_format == "aac":
|
|
|
|
raise ValueError(
|
|
|
|
"AAC format is not currently supported. Please use wav, mp3, opus, or flac."
|
|
|
|
)
|
|
|
|
|
|
|
|
elif output_format == "pcm":
|
|
|
|
raise ValueError(
|
|
|
|
"PCM format is not currently supported. Please use wav, mp3, opus, or flac."
|
|
|
|
)
|
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
else:
|
2024-12-31 01:57:00 -07:00
|
|
|
raise ValueError(
|
|
|
|
f"Format {output_format} not supported. Supported formats are: wav, mp3, opus, flac."
|
|
|
|
)
|
|
|
|
|
2024-12-31 01:52:16 -07:00
|
|
|
except Exception as e:
|
|
|
|
logger.error(f"Error converting audio to {output_format}: {str(e)}")
|
|
|
|
raise ValueError(f"Failed to convert audio to {output_format}: {str(e)}")
|