Files
2026-10-18 19:01:04 -07:00

75 lines
2.2 KiB
Python

# Copyright 2026 Umbra Tools (umbratools.com)
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import logging
from pathlib import Path
from typing import Any
logger = logging.getLogger(__name__)
class AudioGenerator:
def __init__(self, tts_engine: Any, quality_checker: Any, config: Any) -> None:
self.tts = tts_engine
self.quality = quality_checker
self.config = config
async def generate_utterance(
self,
utterance: dict[str, Any],
output_path: Path,
) -> dict[str, Any]:
voice_ref = utterance.get("voice_ref")
instruct = utterance.get("instruct")
text = utterance["text"]
try:
result_path = self.tts.generate(
text=text,
output_path=output_path,
voice_ref=Path(voice_ref) if voice_ref else None,
instruct=instruct,
)
quality = self.quality.check_audio_quality(result_path)
return {
"status": "generated",
"path": str(result_path),
"quality": quality,
}
except Exception as e:
logger.error("Generation failed for utterance %s: %s", utterance.get("id"), e)
return {
"status": "failed",
"error": str(e),
}
async def generate_chapter(
self,
manifest: dict[str, Any],
output_dir: Path,
) -> dict[str, Any]:
output_dir.mkdir(parents=True, exist_ok=True)
results = []
for utterance in manifest.get("utterances", []):
utt_id = utterance["id"]
out_path = output_dir / f"{utt_id}.wav"
result = await self.generate_utterance(utterance, out_path)
results.append(result)
successful = sum(1 for r in results if r["status"] == "generated")
failed = sum(1 for r in results if r["status"] == "failed")
return {
"chapter_id": manifest.get("chapter_id"),
"total_utterances": len(results),
"successful": successful,
"failed": failed,
"results": results,
}