### Initialize and Start Project Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Commands to initialize the environment, install dependencies, and start the development 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 ``` -------------------------------- ### Manual project setup with Python and pnpm Source: https://github.com/deepgram-starters/django-flux/blob/main/README.md Alternative setup method for cloning the repository and installing dependencies manually. Requires adding the DEEPGRAM_API_KEY to the .env file. ```bash git clone --recurse-submodules https://github.com/deepgram-starters/django-flux.git cd django-flux pip install -r requirements.txt cd frontend && corepack pnpm install && cd .. cp sample.env .env # Add your DEEPGRAM_API_KEY ``` -------------------------------- ### Install Dependencies Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Commands to install backend Python requirements and frontend Node.js dependencies. ```bash python3 -m venv venv && ./venv/bin/pip install -r requirements.txt Frontend: cd frontend && corepack pnpm install ``` -------------------------------- ### Start and Stop Commands Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Commands for managing the application lifecycle, including starting, stopping, and cleaning the build. ```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 ``` -------------------------------- ### Initialize and Run Project Source: https://context7.com/deepgram-starters/django-flux/llms.txt Commands for cloning the repository, installing dependencies, configuring environment variables, and managing server processes. ```bash # Clone the repository with submodules git clone --recurse-submodules https://github.com/deepgram-starters/django-flux.git cd django-flux # Initialize and install all dependencies make init # Configure environment variables cp sample.env .env # Edit .env with your Deepgram API key # Required: # DEEPGRAM_API_KEY=your_api_key_here # # Optional: # PORT=8081 # Backend server port # HOST=0.0.0.0 # Server bind address # SESSION_SECRET=xxx # JWT signing secret (auto-generated if not set) # Start both backend and frontend servers make start # Backend: http://localhost:8081 # Frontend: http://localhost:8080 # Or start servers separately make start-backend # Start Django/Daphne on port 8081 make start-frontend # Start Vite dev server on port 8080 # Run conformance tests (requires running servers) make test # Clean build artifacts make clean # Update submodules to latest make update # Check project status make status ``` -------------------------------- ### Initialize and start project with Makefile Source: https://github.com/deepgram-starters/django-flux/blob/main/README.md Recommended method for local development. Ensure the DEEPGRAM_API_KEY is added to the .env file after copying from sample.env. ```bash make init cp sample.env .env # Add your DEEPGRAM_API_KEY make start ``` -------------------------------- ### Run backend and frontend servers Source: https://github.com/deepgram-starters/django-flux/blob/main/README.md Commands to start the backend and frontend services in separate terminal sessions. ```bash # Terminal 1 - Backend (port 8081) python3 app.py # Terminal 2 - Frontend (port 8080) cd frontend && corepack pnpm run dev -- --port 8080 --no-open ``` -------------------------------- ### Conventional Commit Examples Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Standardized commit message formats for the project. ```text feat(django-flux): add diarization support fix(django-flux): resolve WebSocket close handling refactor(django-flux): simplify session endpoint chore(deps): update frontend submodule ``` -------------------------------- ### Configure Django Settings for Flux Source: https://context7.com/deepgram-starters/django-flux/llms.txt Sets up the environment, installed applications, and WebSocket infrastructure for the Django Flux project. ```python import os from pathlib import Path from dotenv import load_dotenv load_dotenv() BASE_DIR = Path(__file__).resolve().parent.parent PORT = int(os.environ.get('PORT', 8081)) HOST = os.environ.get('HOST', '0.0.0.0') SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'django-insecure-dev-key') DEBUG = True ALLOWED_HOSTS = ['*'] INSTALLED_APPS = [ 'daphne', # ASGI server for WebSocket support 'corsheaders', # CORS handling 'channels', # Django Channels for WebSocket 'starter', # Application module ] # ASGI application for WebSocket support ASGI_APPLICATION = 'config.asgi.application' # CORS configuration for frontend CORS_ALLOW_ALL_ORIGINS = True # Channels settings - in-memory for development CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels.layers.InMemoryChannelLayer' } } ``` -------------------------------- ### Add Keyterms via Query Parameters Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Example of passing multiple keyterm parameters to the WebSocket URL for vocabulary boosting. ```text ?keyterm=Deepgram&keyterm=Nova&keyterm=Aura ``` -------------------------------- ### Run Project Tests and Endpoint Checks Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Commands to execute conformance tests and verify API endpoints. ```bash # Run conformance tests (requires app to be running) make test # Manual endpoint check curl -sf http://localhost:8081/api/metadata | python3 -m json.tool curl -sf http://localhost:8081/api/session | python3 -m json.tool ``` -------------------------------- ### Retrieve Application Metadata via cURL Source: https://context7.com/deepgram-starters/django-flux/llms.txt Retrieves project configuration details including use case, language, and framework tags. ```bash # Get application metadata curl -X GET http://localhost:8081/api/metadata # Response { "title": "Django Flux", "description": "Get started using Deepgram's Flux real-time transcription with this Django demo app", "author": "Deepgram DX Team (https://developers.deepgram.com)", "repository": "https://github.com/deepgram-starters/django-flux", "useCase": "flux", "language": "python", "framework": "django", "tags": ["flux", "streaming", "speech-to-text", "real-time", "turn-detection", "django", "python"] } ``` -------------------------------- ### Environment Variable Template Source: https://context7.com/deepgram-starters/django-flux/llms.txt Template for configuring required API keys and optional server settings in the .env file. ```bash # sample.env - Environment variable template # Required - Get your key at https://console.deepgram.com DEEPGRAM_API_KEY=your_api_key_here # Optional - Server configuration PORT=8081 # Backend API server port (default: 8081) HOST=0.0.0.0 # Server bind address (default: 0.0.0.0) # Optional - Production security SESSION_SECRET=your_secret_key_here # JWT signing secret (auto-generated if not set) # Django configuration (optional) DJANGO_SECRET_KEY=your_django_secret # Django secret key for production ``` -------------------------------- ### Configure URL and WebSocket Routing Source: https://context7.com/deepgram-starters/django-flux/llms.txt Definitions for HTTP REST endpoints and WebSocket consumers using Django Channels. ```python # config/urls.py - HTTP URL routing from django.urls import path, include urlpatterns = [ path('api/', include('starter.urls')), # REST API endpoints ] # starter/urls.py - API endpoint definitions from django.urls import path from . import views urlpatterns = [ path('session', views.get_session, name='session'), # GET /api/session path('metadata', views.metadata, name='metadata'), # GET /api/metadata ] # starter/routing.py - WebSocket URL routing from django.urls import path from . import consumers websocket_urlpatterns = [ path('api/flux', consumers.FluxConsumer.as_asgi()), # WS /api/flux ] # config/asgi.py - ASGI application configuration 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(), "websocket": URLRouter(websocket_urlpatterns), }) ``` -------------------------------- ### Initialize and Connect WebSocket Consumer Source: https://context7.com/deepgram-starters/django-flux/llms.txt Initializes the consumer, validates JWT for authentication, accepts the WebSocket connection, and establishes a connection to the Deepgram API with specified parameters. ```python from channels.generic.websocket import AsyncWebsocketConsumer import websockets import jwt import asyncio import json from urllib.parse import parse_qs, urlencode DEEPGRAM_STT_URL = "wss://api.deepgram.com/v2/listen" DEFAULT_MODEL = "flux-general-en" class FluxConsumer(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): # Validate JWT from subprotocol (access_token.) 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) # Unauthorized return await self.accept(subprotocol=valid_proto) # Parse query parameters from scope query_string = self.scope.get('query_string', b'').decode('utf-8') params = parse_qs(query_string) # Build Deepgram connection with parameters deepgram_params = { 'model': DEFAULT_MODEL, 'encoding': params.get('encoding', ['linear16'])[0], 'sample_rate': params.get('sample_rate', ['16000'])[0], } # Optional EOT parameters if eot_threshold := params.get('eot_threshold', [None])[0]: deepgram_params['eot_threshold'] = eot_threshold if eager_eot := params.get('eager_eot_threshold', [None])[0]: deepgram_params['eager_eot_threshold'] = eager_eot if timeout := params.get('eot_timeout_ms', [None])[0]: deepgram_params['eot_timeout_ms'] = timeout # Add keyterms deepgram_url = f"{DEEPGRAM_STT_URL}?{urlencode(deepgram_params)}" for term in params.get('keyterm', []): deepgram_url += f"&keyterm={term}" # Connect to Deepgram self.deepgram_ws = await websockets.connect( deepgram_url, additional_headers={"Authorization": f"Token {API_KEY}"} ) # Start forwarding responses from Deepgram self.forward_task = asyncio.create_task(self.forward_from_deepgram()) ``` -------------------------------- ### Connect to Flux WebSocket Client Source: https://context7.com/deepgram-starters/django-flux/llms.txt Establishes a WebSocket connection with JWT authentication and streams audio data using the MediaRecorder API. ```javascript // JavaScript client example for connecting to Flux WebSocket // First, get a session token const sessionResponse = await fetch('http://localhost:8081/api/session'); const { token } = await sessionResponse.json(); // Build WebSocket URL with transcription parameters const params = new URLSearchParams({ encoding: 'linear16', // Audio encoding: 'linear16' or 'opus' sample_rate: '16000', // Sample rate: 8000-48000 eot_threshold: '0.7', // End-of-turn confidence: 0.0-1.0 (higher = more conservative) eager_eot_threshold: '0.5', // Tentative EOT threshold (optional) eot_timeout_ms: '5000' // Silence timeout in ms: 0-30000 }); // Add custom vocabulary hints (keyterms) ['Deepgram', 'Nova', 'Aura'].forEach(term => { params.append('keyterm', term); }); const wsUrl = `ws://localhost:8081/api/flux?${params.toString()}`; // Connect with JWT authentication via subprotocol const ws = new WebSocket(wsUrl, [`access_token.${token}`]); ws.onopen = () => { console.log('Connected to Flux API'); // Start streaming audio data as binary }; ws.onmessage = (event) => { const data = JSON.parse(event.data); switch (data.type) { case 'StartOfTurn': console.log('User started speaking'); break; case 'Update': console.log('Interim transcript:', data.transcript); break; case 'EagerEndOfTurn': console.log('Tentative end detected:', data.transcript); break; case 'TurnResumed': console.log('User continued speaking after eager EOT'); break; case 'EndOfTurn': console.log('Final transcript:', data.transcript); break; case 'Error': console.error('Error:', data.description, data.code); break; } }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; ws.onclose = (event) => { console.log(`Connection closed: ${event.code}`); }; // Stream audio data (example with MediaRecorder) navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' }); mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0 && ws.readyState === WebSocket.OPEN) { ws.send(event.data); } }; mediaRecorder.start(250); // Send audio every 250ms }); ``` -------------------------------- ### Update Frontend Submodule Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Commands to commit and push changes within the frontend submodule and update the parent repository reference. ```bash cd frontend && git add . && git commit -m "feat: description" ``` ```bash cd frontend && git push origin main ``` ```bash cd .. && git add frontend && git commit -m "chore(deps): update frontend submodule" ``` -------------------------------- ### API Endpoints Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Overview of the available API endpoints for session management, metadata retrieval, and real-time transcription. ```APIDOC ## API Endpoints | Endpoint | Method | Auth | Purpose | |----------|--------|------|---------| | `/api/session` | GET | None | Issue JWT session token | | `/api/metadata` | GET | None | Return app metadata (useCase, framework, language) | | `/api/flux` | WS | JWT | Advanced real-time transcription with turn-based detection. | ``` -------------------------------- ### Retrieve Session Token via cURL Source: https://context7.com/deepgram-starters/django-flux/llms.txt Fetches a JWT session token for WebSocket authentication and demonstrates its use in protected API requests. ```bash # Request a session token curl -X GET http://localhost:8081/api/session # Response { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3MDk4MjE0NjAsImV4cCI6MTcwOTgyNTA2MH0.abc123..." } # Use the token in subsequent authenticated requests curl -X GET http://localhost:8081/api/protected \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` -------------------------------- ### Flux WebSocket API Source: https://github.com/deepgram-starters/django-flux/blob/main/AGENTS.md Details on connecting to the Flux WebSocket API for advanced real-time transcription, including authentication and customizable parameters. ```APIDOC ## WebSocket API: `/api/flux` ### Description Connects to the Deepgram Flux v2 Listen API for advanced real-time transcription with turn-based detection. ### Method WS (WebSocket) ### Endpoint `wss://api.deepgram.com/v2/listen` (proxied via backend) ### Authentication JWT session tokens are required. The WebSocket subprotocol should be `access_token.`. ### Query Parameters Flux extends live transcription with end-of-turn (EOT) detection. These are passed as WebSocket URL query parameters: #### Path Parameters None #### Query Parameters - **model** (string) - Optional - Defaults to `flux-general-en`. Specifies the Flux STT model. - **encoding** (string) - Optional - Defaults to `linear16`. Audio encoding format (`linear16`, `opus`). - **sample_rate** (integer) - Optional - Defaults to `16000`. Audio sample rate (`8000`-`48000`). - **eot_threshold** (float) - Optional - Defaults to `0.7`. Confidence threshold for end-of-turn detection (`0.0`-`1.0`). Higher values are more conservative. - **eager_eot_threshold** (float) - Optional - Defaults to disabled. Threshold for tentative (eager) end-of-turn detection (`0.0`-`1.0`). - **eot_timeout_ms** (integer) - Optional - Defaults to `5000`. Silence duration in milliseconds before automatic EOT (`0`-`30000`). - **keyterm** (string) - Optional - Can be specified multiple times. Custom vocabulary hints. ### Request Body None (audio is streamed over the WebSocket connection). ### Response Flux provides structured turn-based events: - **StartOfTurn**: User started speaking. - **Update**: Interim transcript update within the turn. - **EagerEndOfTurn**: Tentative end detected. - **TurnResumed**: User spoke again after eager EOT. - **EndOfTurn**: Confirmed end of turn (final transcript). ### Response Example ```json { "type": "StartOfTurn" } ``` ```json { "type": "Update", "transcript": "This is an interim update." } ``` ```json { "type": "EndOfTurn", "transcript": "This is the final transcript for the turn." } ``` ### Customization Examples **Adding Keyterms:** To add keyterms like "Deepgram", "Nova", and "Aura", append them as repeated query parameters: `?keyterm=Deepgram&keyterm=Nova&keyterm=Aura` **Tuning EOT Behavior:** - To make turn endings faster (more conservative), lower `eot_threshold` (e.g., `0.3`). - To wait longer for pauses, increase `eot_threshold` (e.g., `0.9`). - To enable tentative completions, set `eager_eot_threshold` (e.g., `0.5`). - To reduce silence timeout, lower `eot_timeout_ms` (e.g., `2000`). ``` -------------------------------- ### Implement JWT Authentication Decorator Source: https://context7.com/deepgram-starters/django-flux/llms.txt A decorator for validating JWT tokens in the Authorization header. It returns a 401 status code if the token is missing, expired, or invalid. ```python import functools import os import secrets import time import jwt 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:] 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 @require_session def protected_endpoint(request): return JsonResponse({"message": "Authenticated successfully"}) ``` -------------------------------- ### Forward Audio Data to Deepgram Source: https://context7.com/deepgram-starters/django-flux/llms.txt Handles incoming messages from the client and forwards audio data or text messages to the connected Deepgram WebSocket. ```python async def receive(self, text_data=None, bytes_data=None): # Forward audio data 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) ``` -------------------------------- ### Forward Deepgram Responses to Client Source: https://context7.com/deepgram-starters/django-flux/llms.txt Continuously listens for messages from Deepgram and forwards them back to the connected WebSocket client. Stops if the stop event is set. ```python async def forward_from_deepgram(self): # Forward transcription results to client async for message in self.deepgram_ws: if self.stop_event.is_set(): break if isinstance(message, bytes): await self.send(bytes_data=message) else: await self.send(text_data=message) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.