feat: [api] Fetch audio file for adventure entry
This commit is contained in:
parent
cc9b951b05
commit
e40574ae9d
3 changed files with 33 additions and 3 deletions
|
|
@ -192,7 +192,7 @@ class AdventureService:
|
||||||
max_tokens=2048,
|
max_tokens=2048,
|
||||||
)
|
)
|
||||||
|
|
||||||
story_text, choices_parsed, gm_notes = parse_entry_response(raw_text)
|
story_text, choices_parsed, gm_notes, story_so_far = parse_entry_response(raw_text)
|
||||||
|
|
||||||
await self.entry_repo.update_content(
|
await self.entry_repo.update_content(
|
||||||
entry_id=entry_id,
|
entry_id=entry_id,
|
||||||
|
|
@ -222,7 +222,8 @@ class AdventureService:
|
||||||
)
|
)
|
||||||
|
|
||||||
voice = self.gemini_client.get_voice_by_language(adventure.language)
|
voice = self.gemini_client.get_voice_by_language(adventure.language)
|
||||||
wav_bytes = await self.gemini_client.generate_audio(story_text, voice)
|
story_text_with_tag = "[like a dungeons and dragons gamemaster] " + story_text
|
||||||
|
wav_bytes = await self.gemini_client.generate_audio(story_text_with_tag, voice)
|
||||||
audio_key = f"adventure-audio/{entry_id}.wav"
|
audio_key = f"adventure-audio/{entry_id}.wav"
|
||||||
upload_audio(audio_key, wav_bytes)
|
upload_audio(audio_key, wav_bytes)
|
||||||
await self.audio_repo.create(
|
await self.audio_repo.create(
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ def build_entry_system_prompt(
|
||||||
f"only \"-----\".\n"
|
f"only \"-----\".\n"
|
||||||
f"- Part 1: the story entry, {min_length}–{max_length} words, speaking directly to the player.\n"
|
f"- Part 1: the story entry, {min_length}–{max_length} words, speaking directly to the player.\n"
|
||||||
f"- Part 2: exactly 4 numbered player options, one per line, labelled \"1.\", \"2.\", \"3.\", \"4.\".\n"
|
f"- Part 2: exactly 4 numbered player options, one per line, labelled \"1.\", \"2.\", \"3.\", \"4.\".\n"
|
||||||
f"- Part 3: GM notes to your future self (hidden from the player). "
|
f"- Part 3: GM notes to your future self (hidden from the player). \n"
|
||||||
f"If no notes, write \"no notes\".\n"
|
f"If no notes, write \"no notes\".\n"
|
||||||
f"- Your first message must establish: who the player is, the setting, and the broad direction.\n"
|
f"- Your first message must establish: who the player is, the setting, and the broad direction.\n"
|
||||||
f"- No sexual content or graphic violence. Romance, threat, and adventure are fine (12-certificate)."
|
f"- No sexual content or graphic violence. Romance, threat, and adventure are fine (12-certificate)."
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import uuid
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from fastapi.responses import Response
|
from fastapi.responses import Response
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
@ -5,11 +7,37 @@ from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from ..outbound.postgres.database import get_db
|
from ..outbound.postgres.database import get_db
|
||||||
from ..outbound.postgres.repositories.translated_article_repository import TranslatedArticleRepository
|
from ..outbound.postgres.repositories.translated_article_repository import TranslatedArticleRepository
|
||||||
|
from ..outbound.postgres.repositories.adventure_repository import PostgresAdventureEntryAudioRepository
|
||||||
from ..storage import download_audio
|
from ..storage import download_audio
|
||||||
|
|
||||||
router = APIRouter(prefix="/media", tags=["media"])
|
router = APIRouter(prefix="/media", tags=["media"])
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/adventure-audio/{filename:path}")
|
||||||
|
async def get_adventure_audio_file(
|
||||||
|
filename: str,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
) -> Response:
|
||||||
|
try:
|
||||||
|
eid = uuid.UUID(filename.rsplit(".", 1)[0])
|
||||||
|
except ValueError:
|
||||||
|
raise HTTPException(status_code=400, detail="Invalid file ID")
|
||||||
|
|
||||||
|
print(f"Looking for adventure audio with entry ID: {eid}")
|
||||||
|
|
||||||
|
adventure_audio = await PostgresAdventureEntryAudioRepository(db).get_for_entry(entry_id=eid, component_type="story_text")
|
||||||
|
|
||||||
|
if adventure_audio is None:
|
||||||
|
raise HTTPException(status_code=404, detail="File not found")
|
||||||
|
try:
|
||||||
|
audio_bytes, content_type = download_audio("adventure-audio/" + filename)
|
||||||
|
except ClientError as e:
|
||||||
|
if e.response["Error"]["Code"] in ("NoSuchKey", "404"):
|
||||||
|
raise HTTPException(status_code=404, detail="File not found")
|
||||||
|
raise HTTPException(status_code=500, detail="Storage error")
|
||||||
|
|
||||||
|
return Response(content=audio_bytes, media_type=content_type)
|
||||||
|
|
||||||
@router.get("/{filename:path}")
|
@router.get("/{filename:path}")
|
||||||
async def get_media_file(
|
async def get_media_file(
|
||||||
filename: str,
|
filename: str,
|
||||||
|
|
@ -28,3 +56,4 @@ async def get_media_file(
|
||||||
raise HTTPException(status_code=500, detail="Storage error")
|
raise HTTPException(status_code=500, detail="Storage error")
|
||||||
|
|
||||||
return Response(content=audio_bytes, media_type=content_type)
|
return Response(content=audio_bytes, media_type=content_type)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue