### Initialize Local Development Environment Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Commands to sync backend dependencies, install frontend packages, and start the development services. ```bash uv sync # backend deps cd frontend && npm install && cd .. make dev # starts PostgreSQL, runs migrations, then backend (:8002) + frontend (:5174) ``` -------------------------------- ### Install Yuralume-Core via One-line Command Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Use these commands to pull and run the prebuilt Docker stack. Requires Docker Desktop installed. ```bash curl -fsSL https://yuralume.com/install.sh | bash ``` ```powershell irm https://yuralume.com/install.ps1 | iex ``` -------------------------------- ### GET /voices Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Retrieves the list of available character voices for the voice picker. ```APIDOC ## GET /voices ### Description Retrieves the catalog of available voices. The app uses this to populate the character voice picker. ### Method GET ### Endpoint {base_url}/voices ### Response #### Success Response (200) - **voices** (array) - List of available voices. - **id** (string) - Required. The stable voice identifier. - **label** (string) - Human-readable name. - **prompt_lang** (string) - Language tag of the reference sample. - **is_complete** (boolean) - Indicates if the voice is fully set up. #### Response Example { "voices": [ { "id": "mira", "label": "Mira (calm)", "prompt_lang": "ja", "is_complete": true } ] } ``` -------------------------------- ### GET /voices Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Retrieves the list of available voices from the custom TTS server. ```APIDOC ## GET /voices ### Description Fetches the catalog of voices available on the custom TTS server. ### Method GET ### Endpoint {base_url}/voices ### Request Headers - **Authorization** (string) - Optional - Bearer - **X-Request-Id** (string) - Required - tts- ``` -------------------------------- ### GET /voices Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Retrieves the list of available voices supported by the custom TTS server. ```APIDOC ## GET /voices ### Description Returns a list of voices available for selection in the character voice picker. ### Method GET ### Endpoint /voices ### Response #### Success Response (200) - **voices** (array) - List of voice objects - **id** (string) - Unique identifier for the voice - **label** (string) - Display name for the voice - **prompt_lang** (string) - Language code for the prompt - **is_complete** (boolean) - Status of the voice configuration #### Response Example { "voices": [ { "id": "mira", "label": "Mira (calm)", "prompt_lang": "ja", "is_complete": true } ] } ``` -------------------------------- ### Voice catalog response structure Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md The expected JSON response format for the GET /voices endpoint, containing a list of available voice objects. ```json { "voices": [ { "id": "mira", "label": "Mira (calm)", "prompt_lang": "ja", "is_complete": true } ] } ``` -------------------------------- ### Minimal ComfyUI Gateway Implementation Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md A FastAPI-based starter service that proxies image generation requests to a local ComfyUI instance. Requires a workflow.json file and assumes a trusted LAN environment. ```python # gateway.py — minimal Custom Media Gateway starter. Not tuned. # pip install fastapi uvicorn httpx import json, uuid, asyncio from pathlib import Path import httpx from fastapi import FastAPI from fastapi.responses import Response from pydantic import BaseModel COMFY = "http://127.0.0.1:8188" WORKFLOW = json.loads(Path("workflow.json").read_text()) # one hardcoded workflow PROMPT_NODE = "6" # the id of your CLIPTextEncode (positive) node in workflow.json app = FastAPI() _artifacts: dict[str, bytes] = {} # in-memory; fine for a LAN starter class ImageRequest(BaseModel): model: str prompt: str size: str = "1024x1024" n: int = 1 @app.post("/images/generations") async def images_generations(req: ImageRequest): # NOTE (starter): prompt goes in verbatim. A real gateway rewrites the # prompt per model (SDXL tags / z-image bilingual / ideogram JSON / ...). wf = json.loads(json.dumps(WORKFLOW)) # deep copy wf[PROMPT_NODE]["inputs"]["text"] = req.prompt # inject Core's prompt async with httpx.AsyncClient(timeout=180) as http: queued = await http.post(f"{COMFY}/prompt", json={"prompt": wf}) prompt_id = queued.json()["prompt_id"] # poll history until this prompt finishes while True: hist = (await http.get(f"{COMFY}/history/{prompt_id}")).json() if prompt_id in hist: break await asyncio.sleep(1.0) # pull the first output image ComfyUI produced outputs = hist[prompt_id]["outputs"] img = next(o["images"][0] for o in outputs.values() if o.get("images")) raw = await http.get( f"{COMFY}/view", params={"filename": img["filename"], "subfolder": img.get("subfolder", ""), "type": img.get("type", "output")}, ) art_id = uuid.uuid4().hex _artifacts[art_id] = raw.content # relative url; Core resolves it against base_url and GETs it WITHOUT auth return {"data": [{"url": f"/artifacts/{art_id}"}]} @app.get("/artifacts/{art_id}") def artifact(art_id: str): # unauthenticated on purpose — trusted LAN only (see gotcha 2) return Response(content=_artifacts.get(art_id, b""), media_type="image/png") # run: uvicorn gateway:app --host 0.0.0.0 --port 8000 ``` -------------------------------- ### Self-host with Docker Compose (End User) Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Commands to download configuration files and deploy the stack without cloning the repository. ```bash mkdir yuralume && cd yuralume curl -O https://raw.githubusercontent.com/Yuralume/yuralume-core/main/docker-compose.container.yml curl -O https://raw.githubusercontent.com/Yuralume/yuralume-core/main/.env.container.example cp .env.container.example .env.container # (edit .env.container — at minimum set APP_BASE_URL, CONFIG_ENCRYPTION_KEY and STORAGE_KEY) docker compose -f docker-compose.container.yml --profile storage-local pull docker compose -f docker-compose.container.yml --profile storage-local up -d ``` -------------------------------- ### Self-host with Docker Compose (Source Checkout) Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Commands for developers to build and run the stack from a local source checkout. ```powershell Copy-Item .env.container.example .env.container docker compose -f docker-compose.container.yml --profile storage-local up -d --build ``` -------------------------------- ### Implement a minimal Custom TTS Server gateway Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md A starter FastAPI implementation that maps internal voice IDs to backend-specific reference audio and parameters. Requires the httpx and fastapi libraries. ```python # tts_gateway.py — minimal Custom TTS Server starter. Not tuned. # pip install fastapi uvicorn httpx import httpx from fastapi import FastAPI, Response from pydantic import BaseModel SOVITS = "http://127.0.0.1:9880" # GPT-SoVITS api_v2.py # The one place to hide backend quirks: map a stable voice_id the player # picks to whatever THIS engine needs (reference audio + its transcript). # A real server also switches GPT/SoVITS weights per voice here. VOICES = { "mira": { "label": "Mira (calm)", "prompt_lang": "ja", "ref_audio_path": "/gpt_sovits/refs/mira.wav", "prompt_text": "こんにちは、今日はいい天気ですね。", }, } app = FastAPI() class SynthOptions(BaseModel): text_lang: str = "zh" prompt_lang: str = "zh" speed_factor: float = 1.0 class SynthRequest(BaseModel): text: str voice_id: str feature_key: str = "chat" options: SynthOptions = SynthOptions() @app.get("/voices") def voices(): return { "voices": [ { "id": vid, "label": v["label"], "prompt_lang": v["prompt_lang"], "is_complete": True, } for vid, v in VOICES.items() ] } @app.post("/tts/synthesize") async def synthesize(req: SynthRequest): voice = VOICES.get(req.voice_id) if voice is None: # 404 → Core treats this voice as unavailable (greys the play button) return Response(status_code=404) params = { "text": req.text, "text_lang": req.options.text_lang, "ref_audio_path": voice["ref_audio_path"], "prompt_text": voice["prompt_text"], "prompt_lang": voice["prompt_lang"] or req.options.prompt_lang, "speed_factor": req.options.speed_factor, "media_type": "wav", "streaming_mode": "false", } async with httpx.AsyncClient(timeout=90) as http: upstream = await http.get(f"{SOVITS}/tts", params=params) if upstream.status_code != 200: # any non-2xx → Core raises TTSError → 502 (retry might help) return Response(status_code=502) # raw audio bytes in the body — NOT JSON. Content-Type sets the media type. return Response(content=upstream.content, media_type="audio/wav") # run: uvicorn tts_gateway:app --host 0.0.0.0 --port 8100 # register in Admin with base_url = http://:8100 ``` -------------------------------- ### Verify Deployment with Smoke Script Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Run the smoke test script to validate the deployment health, optionally including an OpenAI key for round-trip testing. ```bash uv run python scripts/self_host_smoke.py # baseline (no provider keys) uv run python scripts/self_host_smoke.py --openai-key sk-... # BYOK round-trip too ``` -------------------------------- ### Project Directory Structure Source: https://github.com/yuralume/yuralume-core/blob/main/README.md The project follows a modular structure separating API routes, application logic, domain entities, and infrastructure adapters. ```text src/kokoro_link/ api/ # FastAPI routes application/ # Use cases, DTOs, services bootstrap/ # Container, settings, startup wiring contracts/ # Port interfaces (provider-agnostic) domain/ # Entities, value objects infrastructure/ # Repositories, LLM adapters, persistence frontend/ # Vue 3 + Vite + Ant Design Vue alembic/ # Database migrations docker/ # Local infra Dockerfiles tests/{unit,integration}/ ``` -------------------------------- ### Synthesize HTTP Response Format Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md The server must return raw audio bytes with a corresponding Content-Type header. Core caches these responses based on the returned content. ```http HTTP/1.1 200 OK Content-Type: audio/wav ``` -------------------------------- ### POST /synthesize Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Requests speech synthesis for a given text and voice configuration. ```APIDOC ## POST /synthesize ### Description Submits text to be synthesized into audio using a specified voice and configuration options. ### Method POST ### Request Body - **text** (string) - The line to speak (max 4000 chars). - **voice_id** (string) - The catalog ID of the voice to use. - **feature_key** (string) - The calling surface (e.g., "chat"). - **options** (object) - Configuration options. - **text_lang** (string) - Language of the text (default "zh"). - **prompt_lang** (string) - Language of the voice's reference prompt (default "zh"). - **speed_factor** (float) - Playback speed multiplier (default 1.0). ### Request Example { "text": "今日はいい天気ですね。", "voice_id": "mira", "feature_key": "chat", "options": { "text_lang": "ja", "prompt_lang": "ja", "speed_factor": 1.0 } } ``` -------------------------------- ### Define Video Request Body Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Schema for video generation requests, specifying model, prompt, aspect ratio, and duration. ```json { "model": "yuralume-motion", "prompt": "Character: ...\nScene: ...", "aspect_ratio": "9:16", "duration_seconds": 5 } ``` -------------------------------- ### POST /videos/generations Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Endpoint used by Yuralume Core to request video generation from the custom gateway. ```APIDOC ## POST /videos/generations ### Description Requests a video generation task from the custom media gateway. ### Method POST ### Endpoint {base_url}/videos/generations ### Request Headers - **Authorization** (string) - Required - Bearer - **X-Request-Id** (string) - Required - vid- - **Content-Type** (string) - Required - application/json ``` -------------------------------- ### Probe LLM Capacity Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Measure the capacity of a local OpenAI-compatible LLM endpoint using either raw vLLM mode or Core-integrated chat mode. ```bash uv run python scripts/llm_capacity_probe.py raw-vllm --endpoint http://127.0.0.1:8001/v1 --disable-reasoning --concurrency 1,2,4,8 --requests-per-step 16 uv run python scripts/llm_capacity_probe.py core-chat --core-url http://127.0.0.1:8002 --email admin@example.com --password ... --characters 8 --concurrency 1,2,4,8 --requests-per-step 16 ``` -------------------------------- ### POST /tts/synthesize Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Sends a synthesis request to the custom TTS server to generate audio. ```APIDOC ## POST /tts/synthesize ### Description Requests the server to synthesize speech based on the provided parameters. ### Method POST ### Endpoint {base_url}/tts/synthesize ### Request Headers - **Authorization** (string) - Optional - Bearer - **X-Request-Id** (string) - Required - tts- - **Content-Type** (string) - Required - application/json ``` -------------------------------- ### Video Generation Request Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Defines the structure for requesting video generation from the gateway. ```APIDOC ## Video Request ### Request Body - **model** (string) - Required - Must be set to yuralume-motion. - **prompt** (string) - Required - Contextual description for the video scene. - **aspect_ratio** (string) - Required - One of 9:16, 16:9, or 1:1. - **duration_seconds** (integer) - Required - Requested duration in seconds. ### Request Example { "model": "yuralume-motion", "prompt": "Character: ...\nScene: ...", "aspect_ratio": "9:16", "duration_seconds": 5 } ``` -------------------------------- ### Memoir Localization JSON Schemas Source: https://github.com/yuralume/yuralume-core/blob/main/src/kokoro_link/data/prompts/memoir/localizer.txt Defines the input structure for raw memoir data and the required output structure for localized content. ```json { "chapters": [ { "index": 0, "period": "week", "narrative": "...", "dominant_themes": ["..."], "evidence_quotes": ["..."] } ], "timeline": [ { "index": 0, "kind": "memory|emotion|milestone", "summary": "...", "extras": { "tags": "comma,separated,visible,tags", "emotion_label": "..." } } ] } ``` ```json { "chapters": [ { "index": 0, "narrative": "...", "dominant_themes": ["..."], "evidence_quotes": ["..."] } ], "timeline": [ { "index": 0, "summary": "...", "extras": { "tags": "comma,separated,visible,tags", "emotion_label": "..." } } ] } ``` -------------------------------- ### Generate VAPID Key Pair Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Generates a JSON-formatted VAPID key pair for browser Web Push functionality. ```powershell .venv\Scripts\python.exe -m py_vapid --gen --json ``` -------------------------------- ### Synthesize response Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md The TTS server must return raw audio bytes as the response body. The system uses the Content-Type header to determine the media format, defaulting to audio/wav. ```APIDOC ## [POST] /tts/synthesize ### Description Returns raw audio bytes for the requested text. The response body is treated as the audio clip, and the Content-Type header specifies the audio format (e.g., audio/wav, audio/mpeg). ### Method POST ### Endpoint /tts/synthesize ### Response #### Success Response (200) - **Content-Type** (header) - The MIME type of the audio (e.g., audio/wav, audio/mp3, audio/ogg). - **Body** (binary) - Raw audio bytes of the synthesized speech. #### Response Example HTTP/1.1 200 OK Content-Type: audio/wav ``` -------------------------------- ### POST /tts/synthesize Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Synthesizes text into audio using the specified voice and options. ```APIDOC ## POST /tts/synthesize ### Description Performs text-to-speech synthesis based on the provided text and voice configuration. Returns raw audio bytes. ### Method POST ### Endpoint /tts/synthesize ### Request Body - **text** (string) - The text to synthesize - **voice_id** (string) - The ID of the voice to use - **feature_key** (string) - Feature context key (default: "chat") - **options** (object) - Synthesis configuration - **text_lang** (string) - Language of the input text - **prompt_lang** (string) - Language of the prompt - **speed_factor** (float) - Playback speed multiplier ### Request Example { "text": "Hello world", "voice_id": "mira", "options": { "text_lang": "ja", "prompt_lang": "ja", "speed_factor": 1.0 } } ### Response #### Success Response (200) - **Content-Type** (audio/wav) - Raw audio bytes #### Error Response (404) - Voice ID not found. #### Error Response (502) - Upstream synthesis failure. ``` -------------------------------- ### Define Image Request Body Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Schema for image generation requests, including model selection, prompt, size, and quantity. ```json { "model": "yuralume-anime", "prompt": "Character: Mira\nAppearance: ...\nCurrent emotion: ...\nScene: ...\nRecent dialogue context: ...", "size": "1024x1536", "n": 1 } ``` -------------------------------- ### POST /images/generations Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Endpoint used by Yuralume Core to request image generation from the custom gateway. ```APIDOC ## POST /images/generations ### Description Requests an image generation task from the custom media gateway. ### Method POST ### Endpoint {base_url}/images/generations ### Request Headers - **Authorization** (string) - Required - Bearer - **X-Request-Id** (string) - Required - img- - **Content-Type** (string) - Required - application/json ``` -------------------------------- ### Image Generation Request Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Defines the structure for requesting image generation from the gateway. ```APIDOC ## Image Request ### Request Body - **model** (string) - Required - Passthrough of the configured image_model. - **prompt** (string) - Required - Multi-line English string containing character and scene context. - **size** (string) - Required - Dimensions: 1024x1536, 1536x1024, or 1024x1024. - **n** (integer) - Required - Number of images to generate (1-4). ### Request Example { "model": "yuralume-anime", "prompt": "Character: Mira\nAppearance: ...\nCurrent emotion: ...\nScene: ...\nRecent dialogue context: ...", "size": "1024x1536", "n": 1 } ``` -------------------------------- ### Gateway Request Headers Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Standard headers included in all POST requests to the gateway. The Authorization header contains the configured API key, and the X-Request-Id provides a unique identifier for tracking. ```http Authorization: Bearer X-Request-Id: img- (or vid- for video) Content-Type: application/json ``` -------------------------------- ### Define Image Response Body Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_MEDIA_GATEWAY_SPEC.md Schema for image generation responses, containing a list of artifacts with either base64 data or URLs. ```json { "data": [ { "url": "/v1/artifacts/abc123" } ] } ``` -------------------------------- ### Story Arc Template JSON Schema Source: https://github.com/yuralume/yuralume-core/blob/main/src/kokoro_link/data/prompts/fusion/adapt_to_arc.txt The required JSON structure for defining a playable story arc, including metadata and a sequence of narrative beats. ```json { "id": "snake_case_unique_template_id", "title": "short display title", "premise": "60-120 character premise that states the playable arc", "theme": "ambition|friendship|loss|discovery|transformation|redemption|custom", "tone": "daily|dramatic|mature|dark|lighthearted", "duration_days": 7, "world_frames": ["modern"], "required_traits": [], "beats": [ { "sequence": 0, "day_offset": 0, "title": "beat title", "summary": "100-150 character runtime instruction for the scene", "tension": "setup|rising|climax|falling|resolution", "scene_type": "encounter|revelation|conflict|resolution|interlude", "location": "optional location", "scene_characters": ["optional NPC or cast labels"], "dramatic_question": "optional scene question", "required": true, "operator_position": "absent|present|central", "operator_note": "optional one sentence, may be empty" } ] } ``` -------------------------------- ### ArcTemplate Draft JSON Schema Source: https://github.com/yuralume/yuralume-core/blob/main/src/kokoro_link/data/prompts/story/arc_series_continuation_draft.txt The required structure for the ArcTemplate draft output. Ensure all fields are populated based on the provided character and series context. ```json { "id": "short_slug", "title": "Draft title", "premise": "Playable premise for the next season", "theme": "custom", "tone": "daily|dramatic|lighthearted|dark|mature", "duration_days": 14, "world_frames": ["modern"], "required_traits": [], "beats": [ { "sequence": 0, "day_offset": 0, "title": "Beat title", "summary": "Concrete playable scene seed", "tension": "setup", "scene_type": "encounter", "location": "optional location", "scene_characters": [], "dramatic_question": "optional dramatic question", "required": true } ] } ``` -------------------------------- ### Define Custom TTS Request Headers Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md Required HTTP headers for both the voice catalog and synthesis endpoints. The Authorization header is only included if an API key is configured in the Core settings. ```http Authorization: Bearer (only sent when an api_key is configured) X-Request-Id: tts- Content-Type: application/json (synthesize only) ``` -------------------------------- ### Synthesize request body structure Source: https://github.com/yuralume/yuralume-core/blob/main/docs/CUSTOM_TTS_SERVER_SPEC.md The JSON payload required for synthesis requests, containing the text to be spoken and associated configuration options. ```json { "text": "今日はいい天気ですね。", "voice_id": "mira", "feature_key": "chat", "options": { "text_lang": "ja", "prompt_lang": "ja", "speed_factor": 1.0 } } ``` -------------------------------- ### Repair User Timezone Source: https://github.com/yuralume/yuralume-core/blob/main/README.md Performs a dry run or applies a timezone correction for a specific user account. ```bash uv run python -m kokoro_link.cli.repair_user_timezone --email alice@example.com --timezone Asia/Taipei uv run python -m kokoro_link.cli.repair_user_timezone --email alice@example.com --timezone Asia/Taipei --apply ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.