diff --git a/api/src/main.py b/api/src/main.py index 81c4c26..f590ff5 100644 --- a/api/src/main.py +++ b/api/src/main.py @@ -3,9 +3,10 @@ from fastapi import BackgroundTasks, FastAPI, Request from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import StreamingResponse +from fastapi.responses import JSONResponse, StreamingResponse from fastapi_utilities import add_timer_middleware +from src.services.storage import StorageManager from src.utils.chat_request import chat_request from src.utils.chat_utils import ( SessionChatItem, @@ -89,3 +90,18 @@ async def generate_audiocast_endpoint( async def get_audiocast_endpoint(session_id: str): result = get_audiocast(session_id) return result + + +@app.get("/get-signed-url", response_model=str) +async def get_signed_url_endpoint(blobname: str): + """ + Get signed URL for generated audiocast + """ + url = StorageManager().get_signed_url(blobname=blobname) + return JSONResponse( + content=url, + headers={ + "Content-Type": "application/json", + "Cache-Control": "public, max-age=86390, immutable", + }, + ) diff --git a/api/src/services/storage.py b/api/src/services/storage.py index 27cc322..28b3326 100644 --- a/api/src/services/storage.py +++ b/api/src/services/storage.py @@ -1,3 +1,4 @@ +import datetime import os from dataclasses import dataclass from io import BytesIO @@ -8,7 +9,7 @@ from google.cloud import storage from pydub import AudioSegment -from api.src.env_var import BUCKET_NAME +from src.env_var import BUCKET_NAME storage_client = storage.Client() bucket = storage_client.bucket(BUCKET_NAME) @@ -92,3 +93,15 @@ def download_from_gcs(self, filename: str): blob.download_to_filename(tmp_file_path) return tmp_file_path + + def get_signed_url(self, blobname, expiration=datetime.timedelta(days=1)): + """get a signed URL for a blob""" + blob = bucket.blob(blobname) + if not blob.exists(): + raise Exception(f"Blob {blobname} does not exist") + + return blob.generate_signed_url( + version="v4", + expiration=expiration, + method="GET", + ) diff --git a/app/src/lib/components/RenderAudiocast.svelte b/app/src/lib/components/RenderAudiocast.svelte new file mode 100644 index 0000000..e399422 --- /dev/null +++ b/app/src/lib/components/RenderAudiocast.svelte @@ -0,0 +1,29 @@ + + + + +{#await getSignedURL()} + +{:then audioURL} + +{:catch error} +
{String(error)}
+{/await} diff --git a/app/src/routes/audiocast/[sessionId=sessionId]/+page.svelte b/app/src/routes/audiocast/[sessionId=sessionId]/+page.svelte index 64e9172..c671a20 100644 --- a/app/src/routes/audiocast/[sessionId=sessionId]/+page.svelte +++ b/app/src/routes/audiocast/[sessionId=sessionId]/+page.svelte @@ -5,6 +5,11 @@ source_content: string; created_at?: string; }; + + function parseScript(script: string) { + const matches = [...script.matchAll(/<(Speaker\d+)>(.*?)<\/Speaker\d+>/gs)]; + return matches.map(([, speaker, content]) => `**${speaker}**: ${content}`).join('\n\n'); + } -{#if !$session$?.summary} - -{:else} - {@const { summary, category } = $session$} - {#await generateAudiocast($session$.id, category, summary)} - - {:then data} -
-			{JSON.stringify(data, null, 2)}
-		
- {:catch error} -
{String(error)}
- {/await} -{/if} +
+ {#if $session$?.summary} + {@const { summary, category } = $session$} + {#await getAudiocast($session$.id, category, summary)} +
+ +
+ {:then data} + {@const script = data.script} + {@const sourceContent = data.source_content} +
+ + + + + Audio Transcript + +
+ {#await parse(parseScript(script)) then parsedContent} + {@html parsedContent} + {/await} +
+
+
+
+ + + + Source Content + +
+ {#await parse(sourceContent) then parsedContent} + {@html parsedContent} + {/await} +
+
+
+
+
+ {:catch error} +
{String(error)}
+ {/await} + {/if} +