2024-03-10 00:05:24 -08:00
|
|
|
from pathlib import Path
|
|
|
|
import subprocess
|
|
|
|
import logging
|
|
|
|
|
|
|
|
import ffmpeg
|
|
|
|
|
|
|
|
logger = logging.getLogger('transcoder')
|
|
|
|
|
|
|
|
|
2024-03-17 15:15:41 -07:00
|
|
|
def open(infile: Path, bufsize: int = 4096):
|
2024-03-10 00:05:24 -08:00
|
|
|
"""
|
|
|
|
Return a stream of mp3 data for the given path on disk.
|
|
|
|
|
|
|
|
If the requested path is an mp3, return a filehandle on the file. Otherwise,
|
|
|
|
invoke ffmpeg to tranascode whatever was requested to mp3 format and return
|
|
|
|
a pipe to ffmpeg's STDOUT.
|
|
|
|
"""
|
|
|
|
suffix = infile.suffix.lower()
|
|
|
|
if suffix == '.mp3':
|
|
|
|
logger.debug(f"Not transcoding mp3 {infile = }")
|
2024-03-17 15:15:41 -07:00
|
|
|
return infile.open('rb', buffering=bufsize)
|
2024-03-10 00:05:24 -08:00
|
|
|
|
|
|
|
ffmpeg_args = (
|
|
|
|
ffmpeg
|
|
|
|
.input(str(infile))
|
|
|
|
.output('-', format='mp3', q=2)
|
|
|
|
.global_args('-hide_banner', '-loglevel', 'quiet')
|
|
|
|
.compile()
|
|
|
|
)
|
|
|
|
|
|
|
|
# Force close STDIN to prevent ffmpeg from trying to read from it. silly ffmpeg.
|
2024-03-17 15:15:41 -07:00
|
|
|
proc = subprocess.Popen(ffmpeg_args, bufsize=bufsize, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
|
2024-03-10 00:05:24 -08:00
|
|
|
proc.stdin.close()
|
|
|
|
logger.debug(f"Spawned ffmpeg (PID {proc.pid}) with args {ffmpeg_args = }")
|
|
|
|
return proc.stdout
|