Skip to content

Commit

Permalink
fix for uploaded audio url for custom element
Browse files Browse the repository at this point in the history
  • Loading branch information
ilkersigirci committed Jan 14, 2025
1 parent 885cae0 commit 245c849
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 18 deletions.
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@
"${workspaceFolder}/src/podflix/gui/mock.py"
],
},
{
"name": "Chainlit Audio",
"type": "debugpy",
"request": "launch",
// "program": "${file}",
"console": "integratedTerminal",
"module": "chainlit",
"justMyCode": false,
"args": [
"run",
"--headless",
"--port",
"5000",
// "${file}",
"${workspaceFolder}/src/podflix/gui/audio.py"
],
},
{
"name": "Debug Current File",
"type": "debugpy",
Expand Down
56 changes: 48 additions & 8 deletions configs/chainlit/public/elements/AudioWithTranscript.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Card, CardHeader, CardContent } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area"
import { Button } from "@/components/ui/button"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
import { Download } from "lucide-react"
import { useRef } from "react"

export default function AudioWithTranscript() {
Expand All @@ -18,17 +21,54 @@ export default function AudioWithTranscript() {
return `${mins}:${secs.toString().padStart(2, '0')}`;
};

const handleDownload = () => {
const content = props.segments
.map(segment => `[${formatTimestamp(segment.start)}] ${segment.text}`)
.join('\n');

const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
// Remove any existing extension and add .txt
const baseFileName = props.name.replace(/\.[^/.]+$/, '');
a.download = baseFileName + '.txt';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
};

return (
<Card className="w-full h-full flex flex-col">
<CardHeader className="pb-2 flex-shrink-0">
<audio
ref={audioRef}
controls
src={props.audioUrl}
className="w-full"
>
Your browser does not support the audio element.
</audio>
<div className="flex justify-between items-center mb-2">
<audio
ref={audioRef}
controls
src={props.url}
className="w-full"
>
Your browser does not support the audio element.
</audio>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={handleDownload}
className="ml-2 flex-shrink-0"
>
<Download className="h-4 w-4" />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Download the transcript</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</CardHeader>
<CardContent className="flex-1 p-0">
<ScrollArea className="h-full w-full rounded-md border p-4">
Expand Down
24 changes: 14 additions & 10 deletions src/podflix/gui/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
from langchain_community.chat_message_histories import ChatMessageHistory
from langfuse.callback import CallbackHandler as LangfuseCallbackHandler
from literalai.helper import utc_now
from loguru import logger

from podflix.env_settings import env_settings
from podflix.graph.podcast_rag import compiled_graph
from podflix.utils.chainlit_utils.data_layer import apply_sqlite_data_layer_fixes
from podflix.utils.chainlit_utils.data_layer import (
apply_sqlite_data_layer_fixes,
get_read_url_of_file,
)
from podflix.utils.chainlit_utils.general import (
create_message_history_from_db_thread,
get_current_chainlit_thread_id,
set_extra_user_session_params,
simple_auth_callback,
)
Expand Down Expand Up @@ -63,7 +66,7 @@ async def on_chat_start():
accept=["audio/*"],
max_files=1,
max_size_mb=50,
timeout=180,
timeout=360,
).send()

file = files[0]
Expand All @@ -75,25 +78,26 @@ async def on_chat_start():

cl.user_session.set("audio_text", audio_text)

logger.debug(f"Audio file path: {file.path}")

# TODO: Fetch the audio url from the db using get_element_url
audio_url = file.path
# NOTE: Workaround to get s3 url of the uploaded file in the current thread
thread_id = get_current_chainlit_thread_id()
audio_url = await get_read_url_of_file(thread_id=thread_id, file_name=file.name)

# Create audio element with transcript and segments
audio_element = cl.CustomElement(
name="AudioWithTranscript",
props={
"audioUrl": audio_url,
"name": file.name,
"url": audio_url,
"segments": segments,
},
display="side",
)

system_message.content = "Audio transcribed successfully 🎉"
system_message.elements.append(audio_element)

system_message.content += "\nAudioWithTranscript"
system_message.content = "Audio transcribed successfully 🎉"
system_message.content += "\nOfficialAudio AudioWithTranscript"

await system_message.update()


Expand Down
29 changes: 29 additions & 0 deletions src/podflix/utils/chainlit_utils/data_layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import boto3
import chainlit as cl
import chainlit.socket
from chainlit.data import get_data_layer
from chainlit.data.sql_alchemy import SQLAlchemyDataLayer
from chainlit.data.storage_clients.s3 import S3StorageClient
from chainlit.element import ElementDict
Expand Down Expand Up @@ -154,6 +155,34 @@ async def get_element_url(
return element_dict.url


async def get_read_url_of_file(thread_id: str, file_name: str) -> str:
"""Retrieve the URL for accessing an file in a thread.
Examples:
>>> data_layer = ChainlitDataLayer()
>>> url = await get_read_url_of_file(data_layer, "thread123", "audio.mp3")
>>> print(url) # URL string
Args:
thread_id: The unique identifier of the thread containing the file.
file_name: The full name of the the file to retrieve, included the file extension.
Returns:
str: The S3 URL string of the file.
Raises:
ValueError: If S3 storage client is not configured in the data layer.
"""
cl_data_layer = get_data_layer()

if cl_data_layer.storage_client is None:
raise ValueError("S3 storage client not set in data layer.")

object_key = f"threads/{thread_id}/files/{file_name}"

return await cl_data_layer.storage_client.get_read_url(object_key=object_key)


def apply_sqlite_data_layer_fixes():
"""Apply necessary fixes for SQLite data layer configuration.
Expand Down
5 changes: 5 additions & 0 deletions src/podflix/utils/chainlit_utils/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,8 @@ def set_extra_user_session_params(
langfuse_session_url = get_lf_session_url(session_id=session_id)

logger.debug(f"Langfuse Session URL: {langfuse_session_url}")


def get_current_chainlit_thread_id() -> str:
"""Get the current Chainlit thread ID."""
return cl.context.session.thread_id

0 comments on commit 245c849

Please sign in to comment.