### Initialize and start project with Makefile Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/README.md Recommended workflow for local setup using the provided Makefile. ```bash make init cp sample.env .env # Add your DEEPGRAM_API_KEY make start ``` -------------------------------- ### Initialize and Start Application with Makefile Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Provides Makefile commands for initializing the project, setting up the environment, and starting both the backend and frontend. ```bash # Quick start with Makefile (recommended) make init # Initialize submodules and install dependencies cp sample.env .env # Create .env file # Edit .env and add your DEEPGRAM_API_KEY make start # Start backend (8081) and frontend (8080) ``` -------------------------------- ### Manual project installation Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/README.md Manual steps to clone the repository, set up a virtual environment, and install dependencies. ```bash git clone --recurse-submodules https://github.com/deepgram-starters/django-live-transcription.git cd django-live-transcription python3 -m venv venv ./venv/bin/pip install -r requirements.txt cd frontend && corepack pnpm install && cd .. cp sample.env .env # Add your DEEPGRAM_API_KEY ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/AGENTS.md Commands to install backend and frontend dependencies. ```bash python3 -m venv venv && ./venv/bin/pip install -r requirements.txt Frontend: cd frontend && corepack pnpm install ``` -------------------------------- ### Initialize and Start Development Servers Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/AGENTS.md Commands to initialize the project environment and launch the backend and frontend servers. ```bash # Initialize (clone submodules + install deps) make init # Set up environment test -f .env || cp sample.env .env # then set DEEPGRAM_API_KEY # Start both servers make start # Backend: http://localhost:8081 # Frontend: http://localhost:8080 ``` -------------------------------- ### Manage Application Lifecycle Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/AGENTS.md Commands to start, stop, or rebuild the application environment. ```bash make start ``` ```bash # Terminal 1 — Backend ./venv/bin/daphne -b 0.0.0.0 -p 8081 config.asgi:application # Terminal 2 — Frontend cd frontend && corepack pnpm run dev -- --port 8080 --no-open ``` ```bash lsof -ti:8080,8081 | xargs kill -9 2>/dev/null ``` ```bash rm -rf venv frontend/node_modules frontend/.vite make init ``` -------------------------------- ### Conventional Commits Examples Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/AGENTS.md Examples of commit messages following the conventional commits format. Use these to maintain a consistent commit history. ```git feat(django-live-transcription): add diarization support ``` ```git fix(django-live-transcription): resolve WebSocket close handling ``` ```git refactor(django-live-transcription): simplify session endpoint ``` ```git chore(deps): update frontend submodule ``` -------------------------------- ### Manual Backend Startup with Daphne Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Manually starts the Django backend using the Daphne ASGI server, specifying host and port. ```bash # Manual Python setup (without Make) git clone --recurse-submodules https://github.com/deepgram-starters/django-live-transcription.git cd django-live-transcription # Create virtual environment and install dependencies python3 -m venv venv ./venv/bin/pip install -r requirements.txt # Install frontend cd frontend && corepack pnpm install && cd .. # Configure environment cp sample.env .env # Edit .env and add DEEPGRAM_API_KEY # Start backend with Daphne ASGI server ./venv/bin/daphne -b 0.0.0.0 -p 8081 config.asgi:application # In separate terminal - start frontend cd frontend && corepack pnpm run dev -- --port 8080 --no-open ``` -------------------------------- ### Run backend and frontend servers Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/README.md Commands to start the Django backend and the frontend development server in separate terminals. ```bash # Terminal 1 - Backend (port 8081) ./venv/bin/daphne -b 0.0.0.0 -p 8081 config.asgi:application # Terminal 2 - Frontend (port 8080) cd frontend && corepack pnpm run dev -- --port 8080 --no-open ``` -------------------------------- ### GET /api/metadata Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Retrieves application metadata from the deepgram.toml configuration file. ```APIDOC ## GET /api/metadata ### Description Returns application metadata including title, description, author, repository, use case, and tags. ### Method GET ### Endpoint /api/metadata ### Response #### Success Response (200) - **title** (string) - Application title - **description** (string) - Application description - **author** (string) - Author information - **repository** (string) - GitHub repository URL - **useCase** (string) - Primary use case - **language** (string) - Programming language - **framework** (string) - Web framework used - **sdk** (string) - SDK information - **tags** (array) - List of relevant tags #### Response Example { "title": "Django Live Transcription", "description": "Get started using Deepgram's Live Transcription with this Django demo app", "author": "Deepgram DX Team (https://developers.deepgram.com)", "repository": "https://github.com/deepgram-starters/django-live-transcription", "useCase": "live-transcription", "language": "python", "framework": "django", "sdk": "N/A", "tags": ["live-transcription", "live-stt", "real-time-transcription"] } ``` -------------------------------- ### GET /api/session Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Retrieves a session token required for authenticating the WebSocket connection. ```APIDOC ## GET /api/session ### Description Retrieves a JWT session token used to authenticate the live transcription WebSocket connection. ### Method GET ### Endpoint /api/session ### Response #### Success Response (200) - **token** (string) - The JWT session token for WebSocket authentication. #### Response Example { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` -------------------------------- ### GET /api/session Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Issues a JWT session token required for authenticating subsequent API and WebSocket requests. ```APIDOC ## GET /api/session ### Description Issues a JWT session token for authenticating subsequent API and WebSocket requests. The token is required for all protected endpoints and WebSocket connections. ### Method GET ### Endpoint /api/session ### Response #### Success Response (200) - **token** (string) - The JWT session token used for authorization. #### Response Example { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` -------------------------------- ### Makefile Commands for Project Management Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Lists various Makefile commands for managing project prerequisites, dependencies, and services. ```bash # Individual commands make check-prereqs # Verify git, python3, pip3 are installed make install-backend # Install Python dependencies only make install-frontend # Install frontend dependencies only make start-backend # Start backend only on port 8081 make start-frontend # Start frontend only on port 8080 make clean # Remove venv, node_modules, and cache files make status # Show git and submodule status ``` -------------------------------- ### Testing Commands Source: https://github.com/deepgram-starters/django-live-transcription/blob/main/AGENTS.md Commands for running conformance tests and manually checking API endpoints. Ensure the application is running before executing these. ```bash # Run conformance tests (requires app to be running) make test ``` ```bash # Manual endpoint check curl -sf http://localhost:8081/api/metadata | python3 -m json.tool ``` ```bash curl -sf http://localhost:8081/api/session | python3 -m json.tool ``` -------------------------------- ### Configure ASGI Application for WebSockets Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Sets up the ASGI application to handle both standard HTTP requests and WebSocket connections, routing WebSockets to Django Channels for processing. ```python import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter, URLRouter from starter.routing import websocket_urlpatterns os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings') application = ProtocolTypeRouter({ "http": get_asgi_application(), # Standard Django HTTP handling "websocket": URLRouter(websocket_urlpatterns), # WebSocket routing }) ``` -------------------------------- ### Environment Configuration (.env file) Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Specifies required and optional environment variables for the application, including Deepgram API key and server settings. ```bash # .env file configuration # Copy from sample.env: cp sample.env .env # Required - Your Deepgram API key DEEPGRAM_API_KEY=your_deepgram_api_key_here # Optional - Backend API server port (default: 8081) PORT=8081 # Optional - Server host (default: 0.0.0.0) HOST=0.0.0.0 # Optional - Session secret for JWT signing (auto-generated if not set) # Set in production for consistent sessions across restarts SESSION_SECRET=your_secure_random_secret ``` -------------------------------- ### Retrieve Application Metadata Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Fetches configuration details from deepgram.toml, including project title, description, and tags. ```python # HTTP GET request to retrieve application metadata # Endpoint: GET /api/metadata import requests response = requests.get("http://localhost:8081/api/metadata") metadata = response.json() # Response format: # { # "title": "Django Live Transcription", # "description": "Get started using Deepgram's Live Transcription with this Django demo app", # "author": "Deepgram DX Team (https://developers.deepgram.com)", # "repository": "https://github.com/deepgram-starters/django-live-transcription", # "useCase": "live-transcription", # "language": "python", # "framework": "django", # "sdk": "N/A", # "tags": ["live-transcription", "live-stt", "real-time-transcription", ...] # } ``` ```bash # Using curl curl http://localhost:8081/api/metadata ``` -------------------------------- ### Django Settings for Channels and CORS Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Configures Django settings, including adding necessary apps like 'daphne' and 'channels', disabling the database, and enabling CORS. ```python # Django settings configuration # Located at: config/settings.py INSTALLED_APPS = [ 'daphne', # Must be first for Channels ASGI 'corsheaders', # CORS support 'channels', # Django Channels for WebSockets 'starter', # Application module ] # No database required - stateless application DATABASES = {} # Channels configuration ASGI_APPLICATION = 'config.asgi.application' CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels.layers.InMemoryChannelLayer' } } # CORS - Allow all origins (configure for production) CORS_ALLOW_ALL_ORIGINS = True ``` -------------------------------- ### Implement LiveTranscriptionConsumer WebSocket Handler Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Placeholder for the Django Channels consumer logic responsible for managing WebSocket lifecycle and Deepgram proxying. ```python # WebSocket consumer implementation ``` -------------------------------- ### Connect to Live Transcription WebSocket in Browser Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Establishes a WebSocket connection to the transcription endpoint using a JWT subprotocol and handles incoming transcription results. ```javascript // Browser JavaScript - Connect to live transcription WebSocket // Endpoint: ws://localhost:8081/api/live-transcription // First obtain a session token const sessionResponse = await fetch('http://localhost:8081/api/session'); const { token } = await sessionResponse.json(); // WebSocket connection parameters const params = new URLSearchParams({ model: 'nova-2', // Deepgram model (default: nova-2) language: 'en', // Language code (default: en) smart_format: 'true', // Enable smart formatting interim_results: 'true', // Return interim results punctuate: 'true', // Add punctuation encoding: 'linear16', // Audio encoding (default: linear16) sample_rate: '16000' // Sample rate in Hz (default: 16000) }); // Connect with JWT token in subprotocol const ws = new WebSocket( `ws://localhost:8081/api/live-transcription?${params}`, [`access_token.${token}`] // JWT passed as WebSocket subprotocol ); ws.onopen = () => { console.log('Connected to live transcription'); // Start sending audio data (as binary) }; ws.onmessage = (event) => { const result = JSON.parse(event.data); // Deepgram transcription response format: // { // "type": "Results", // "channel_index": [0, 1], // "duration": 1.5, // "start": 0.0, // "is_final": true, // "channel": { // "alternatives": [{ // "transcript": "Hello world", // "confidence": 0.98, // "words": [...] // }] // } // } if (result.channel?.alternatives?.[0]?.transcript) { console.log('Transcript:', result.channel.alternatives[0].transcript); } }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; ws.onclose = (event) => { console.log('Connection closed:', event.code, event.reason); // Close codes: // 1000 - Normal closure // 3000 - Connection error // 4401 - Authentication failed }; // Send audio data (PCM 16-bit, 16kHz, mono) function sendAudioData(audioBuffer) { if (ws.readyState === WebSocket.OPEN) { ws.send(audioBuffer); // Send as binary ArrayBuffer } } // Close connection and signal end of audio function stopTranscription() { ws.close(); } ``` -------------------------------- ### WS /api/live-transcription Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt WebSocket endpoint for streaming audio data to Deepgram and receiving real-time transcriptions. ```APIDOC ## WS /api/live-transcription ### Description Establishes a WebSocket connection to proxy audio data to Deepgram's speech-to-text API. Requires a JWT token passed via the WebSocket subprotocol. ### Method WS ### Endpoint ws://localhost:8081/api/live-transcription ### Parameters #### Query Parameters - **model** (string) - Optional - Deepgram model (default: nova-2) - **language** (string) - Optional - Language code (default: en) - **smart_format** (boolean) - Optional - Enable smart formatting - **interim_results** (boolean) - Optional - Return interim results - **punctuate** (boolean) - Optional - Add punctuation - **encoding** (string) - Optional - Audio encoding (default: linear16) - **sample_rate** (integer) - Optional - Sample rate in Hz (default: 16000) ### Request Body - **audio_data** (binary) - Required - Binary audio data (PCM 16-bit, 16kHz, mono) ### Response #### Success Response (200) - **type** (string) - Message type (e.g., "Results") - **channel** (object) - Contains transcription alternatives - **is_final** (boolean) - Indicates if the result is final #### Response Example { "type": "Results", "channel": { "alternatives": [{ "transcript": "Hello world", "confidence": 0.98 }] }, "is_final": true } ``` -------------------------------- ### Define WebSocket URL Patterns Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Defines the URL patterns for WebSocket connections, mapping a specific API endpoint to the LiveTranscriptionConsumer. ```python from django.urls import path from . import consumers websocket_urlpatterns = [ path('api/live-transcription', consumers.LiveTranscriptionConsumer.as_asgi()), ] ``` -------------------------------- ### Django Channels WebSocket Consumer for Deepgram Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt This consumer handles WebSocket connections, validates JWT, connects to Deepgram for transcription, and forwards audio and transcription data. ```python from channels.generic.websocket import AsyncWebsocketConsumer import websockets import jwt import json import asyncio DEEPGRAM_STT_URL = "wss://api.deepgram.com/v1/listen" class LiveTranscriptionConsumer(AsyncWebsocketConsumer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.deepgram_ws = None self.forward_task = None self.stop_event = asyncio.Event() async def connect(self): """Accept WebSocket connection with JWT validation from subprotocol""" # Validate JWT token from subprotocol (format: access_token.{jwt}) protocols = self.scope.get("subprotocols", []) valid_proto = None for proto in protocols: if proto.startswith("access_token."): token = proto[len("access_token."):] try: jwt.decode(token, SESSION_SECRET, algorithms=["HS256"]) valid_proto = proto except Exception: pass break if not valid_proto: await self.close(code=4401) # Authentication failed return await self.accept(subprotocol=valid_proto) # Parse transcription parameters from query string query_string = self.scope.get('query_string', b'').decode('utf-8') params = parse_qs(query_string) model = params.get('model', ['nova-2'])[0] language = params.get('language', ['en'])[0] # ... additional parameters # Connect to Deepgram API deepgram_url = f"{DEEPGRAM_STT_URL}?model={model}&language={language}..." self.deepgram_ws = await websockets.connect( deepgram_url, additional_headers={"Authorization": f"Token {API_KEY}"} ) # Start background task to forward Deepgram responses self.forward_task = asyncio.create_task(self.forward_from_deepgram()) async def receive(self, text_data=None, bytes_data=None): """Forward audio data from client to Deepgram""" if self.deepgram_ws: if bytes_data: await self.deepgram_ws.send(bytes_data) elif text_data: await self.deepgram_ws.send(text_data) async def forward_from_deepgram(self): """Forward transcription results from Deepgram to client""" async for message in self.deepgram_ws: if isinstance(message, bytes): await self.send(bytes_data=message) else: await self.send(text_data=message) async def disconnect(self, close_code): """Cleanup connections on disconnect""" self.stop_event.set() if self.forward_task: self.forward_task.cancel() if self.deepgram_ws: await self.deepgram_ws.close() ``` -------------------------------- ### Obtain Session Token Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt Retrieves a JWT session token required for authenticating WebSocket connections and protected API routes. ```python # HTTP GET request to obtain session token # Endpoint: GET /api/session import requests # Request a session token response = requests.get("http://localhost:8081/api/session") data = response.json() token = data["token"] # Response format: # {"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."} # Token expires after 1 hour (JWT_EXPIRY = 3600 seconds) # Use token in Authorization header for protected routes: headers = {"Authorization": f"Bearer {token}"} ``` ```bash # Using curl curl http://localhost:8081/api/session # Example response: # {"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDk5MjM0NTYsImV4cCI6MTcwOTkyNzA1Nn0.abc123..."} ``` -------------------------------- ### Django JWT Authentication Decorator Source: https://context7.com/deepgram-starters/django-live-transcription/llms.txt This decorator validates JWT tokens from the Authorization header for protected HTTP endpoints. It returns a 401 error if the token is missing, expired, or invalid. ```python import jwt import functools from django.http import JsonResponse SESSION_SECRET = os.environ.get("SESSION_SECRET") or secrets.token_hex(32) JWT_EXPIRY = 3600 # 1 hour def require_session(f): """Decorator that validates JWT from Authorization header.""" @functools.wraps(f) def decorated(request, *args, **kwargs): auth_header = request.headers.get("Authorization", "") if not auth_header.startswith("Bearer "): return JsonResponse({ "error": { "type": "AuthenticationError", "code": "MISSING_TOKEN", "message": "Authorization header with Bearer token is required", } }, status=401) token = auth_header[7:] # Remove "Bearer " prefix try: jwt.decode(token, SESSION_SECRET, algorithms=["HS256"]) except jwt.ExpiredSignatureError: return JsonResponse({ "error": { "type": "AuthenticationError", "code": "INVALID_TOKEN", "message": "Session expired, please refresh the page", } }, status=401) except jwt.InvalidTokenError: return JsonResponse({ "error": { "type": "AuthenticationError", "code": "INVALID_TOKEN", "message": "Invalid session token", } }, status=401) return f(request, *args, **kwargs) return decorated # Usage example - protect an endpoint @require_session def protected_endpoint(request): return JsonResponse({"status": "authenticated"}) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.