ForcePilot/backend/package/yuxi/channels/adapters/feishu/audio.py

75 lines
2.0 KiB
Python
Raw Normal View History

from __future__ import annotations
import logging
import subprocess
import tempfile
from pathlib import Path
logger = logging.getLogger(__name__)
TARGET_SAMPLE_RATE = 48000
TARGET_BITRATE = "64k"
TARGET_FORMAT = "ogg"
TARGET_CODEC = "libopus"
def check_ffmpeg_available() -> bool:
try:
result = subprocess.run(["ffmpeg", "-version"], capture_output=True, timeout=5)
return result.returncode == 0
except (FileNotFoundError, subprocess.TimeoutExpired):
return False
def transcode_to_ogg_opus(
input_data: bytes,
input_format: str = "mp3",
sample_rate: int = TARGET_SAMPLE_RATE,
bitrate: str = TARGET_BITRATE,
) -> bytes | None:
if not check_ffmpeg_available():
logger.warning("[FeishuAudio] FFmpeg not available, skipping transcode")
return None
with tempfile.NamedTemporaryFile(suffix=f".{input_format}", delete=False) as infile:
infile.write(input_data)
input_path = infile.name
output_path = input_path + f".{TARGET_FORMAT}"
try:
cmd = [
"ffmpeg",
"-y",
"-i",
input_path,
"-ar",
str(sample_rate),
"-b:a",
bitrate,
"-c:a",
TARGET_CODEC,
output_path,
]
result = subprocess.run(cmd, capture_output=True, timeout=60)
if result.returncode != 0:
logger.error(
"[FeishuAudio] FFmpeg transcode failed: %s",
result.stderr.decode(errors="replace")[:300],
)
return None
output_bytes = Path(output_path).read_bytes()
logger.info(
"[FeishuAudio] Transcode complete: %d -> %d bytes",
len(input_data),
len(output_bytes),
)
return output_bytes
except Exception as e:
logger.error("[FeishuAudio] Transcode error: %s", e)
return None
finally:
Path(input_path).unlink(missing_ok=True)
Path(output_path).unlink(missing_ok=True)