import uuid import ffmpeg from .progress_socket import progress_socket import tempfile CODEC_OPTS = { "mp3": { "codec": "libmp3lame", "f": "mp3", "qscale:a": "0", }, "flac": { "codec": "flac", "f": "flac", "compression_level": "12", }, "ogg": { "codec": "libopus", "f": "ogg", "b:a": "160K", "application": "audio", }, } # x realtime, measured on deployment hardware (g4dn.xlarge) CODEC_SPEEDS = {"mp3": 26.0, "ogg": 29.7, "flac": 9.4} def download_audio( s3, s3_bucket, s3_key, out_dir, progress_handler=None, out_basename=None, sample_rate=48000, ): if out_basename is None: random_id = uuid.uuid4() out_path = f"{out_dir}/{random_id}.wav" else: out_path = f"{out_dir}/{out_basename}.wav" if progress_handler is None: progress_handler = lambda k, v: None with progress_socket(progress_handler) as socket_filename: process = ( ffmpeg.input("pipe:") .output( out_path, acodec="pcm_f32le", af="aresample=resampler=soxr:precision=28", ar=sample_rate, ) .global_args("-progress", f"unix://{socket_filename}") .run_async(pipe_stdin=True, quiet=True) ) s3.download_fileobj(s3_bucket, s3_key, process.stdin) process.stdin.close() process.wait() return out_path def upload_audio( s3, s3_bucket, s3_key, in_path, codec, progress_handler=None, ): if progress_handler is None: progress_handler = lambda k, v: None with tempfile.TemporaryDirectory() as temp_dir, progress_socket( progress_handler ) as socket_filename: ( ffmpeg.input(in_path) .output(f"{temp_dir}/output", **CODEC_OPTS[codec]) .global_args("-progress", f"unix://{socket_filename}") .run(quiet=True) ) s3.upload_file(f"{temp_dir}/output", s3_bucket, s3_key) def resample_audio( in_path, out_path, sample_rate, progress_handler=None, ): if progress_handler is None: progress_handler = lambda k, v: None with progress_socket(progress_handler) as socket_filename: ( ffmpeg.input(in_path) .output( out_path, af="aresample=resampler=soxr:precision=28", acodec="pcm_f32le", ar=sample_rate, ) .global_args("-progress", f"unix://{socket_filename}") .run(quiet=True) )