<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import asyncio
import aiohttp
import json
import sys
import wave
import os
import struct
import argparse

# Get the API key from the environment variable
api_key = os.environ.get("DEEPGRAM_API_KEY")
if not api_key:
    print("Error: DEEPGRAM_API_KEY environment variable is not set.")
    sys.exit(1)

headers = {
    "Authorization": f"Token {api_key}",
}

async def stream_audio_to_websocket(wav_file_path, language, blank_audio_ms_pre, blank_audio_ms_post, chunk_ms, close_wait):
    # Get sample rate from the WAV file
    with wave.open(wav_file_path, 'rb') as wav_file:
        sample_rate = wav_file.getframerate()

    # URL for Deepgram WebSocket API with dynamic sample rate and language
    deepgram_ws_url = f"wss://api.deepgram.com/v1/listen?model=nova-2&amp;encoding=linear16&amp;sample_rate={sample_rate}&amp;language={language}&amp;smart_format=true"

    print(f"Deepgram WebSocket URL: {deepgram_ws_url}\n")

    async with aiohttp.ClientSession() as session:
        async with session.ws_connect(deepgram_ws_url, headers=headers) as ws:
            print(f"WebSocket connection established with sample rate: {sample_rate} Hz and language: {language}\n")

            async def send_audio_stream(chunk_ms):
                try:
                    with wave.open(wav_file_path, 'rb') as wav_file:
                        params = wav_file.getparams()
                        channels = params.nchannels
                        bytes_per_sample = params.sampwidth

                        # Calculate chunk size based on the specified chunk_ms
                        chunk_size = int(chunk_ms / 1000 * sample_rate * channels * bytes_per_sample)

                        # Send blank audio before file contents
                        if blank_audio_ms_pre &gt; 0:
                            print(f"Sending {blank_audio_ms_pre}ms of blank audio before file contents\n")
                            await send_blank_audio(ws, sample_rate, channels, blank_audio_ms_pre, chunk_size, bytes_per_sample)

                        # Send file contents
                        while True:
                            chunk = wav_file.readframes(chunk_size // (channels * bytes_per_sample))
                            if not chunk:
                                break
                            chunk_bytes = len(chunk)
                            chunk_ms = (chunk_bytes / (channels * bytes_per_sample) / sample_rate) * 1000
                            await ws.send_bytes(chunk)
                            print(f"Sent audio chunk: {chunk_bytes} bytes, {chunk_ms:.2f} ms")
                    
                    # Send blank audio after file contents
                    if blank_audio_ms_post &gt; 0:
                        print(f"Sending {blank_audio_ms_post}ms of blank audio after file contents\n")
                        await send_blank_audio(ws, sample_rate, channels, blank_audio_ms_post, chunk_size, bytes_per_sample)
                    
                    print("Audio file streaming completed.\n")
                except IOError as error:
                    print(f"Error reading WAV file: {error}")
                finally:
                    await ws.send_json({"type": "Finalize"})
                    print("\nSent Finalize message\n")
                    await asyncio.sleep(close_wait)  # Wait for specified seconds
                    await ws.send_json({"type": "CloseStream"})
                    print(f"\nSent CloseStream message after {close_wait} seconds\n")

            async def send_blank_audio(ws, sample_rate, channels, duration_ms, chunk_size, bytes_per_sample):
                blank_frames = int(sample_rate * duration_ms / 1000)
                blank_chunk_size = chunk_size // bytes_per_sample
                for i in range(0, blank_frames, blank_chunk_size):
                    chunk_frames = min(blank_chunk_size, blank_frames - i)
                    blank_chunk = struct.pack(f"&lt;{chunk_frames * channels}h", *([0] * (chunk_frames * channels)))
                    chunk_bytes = len(blank_chunk)
                    chunk_ms = (chunk_frames / sample_rate) * 1000
                    await ws.send_bytes(blank_chunk)
                    print(f"Sent blank audio chunk: {chunk_bytes} bytes, {chunk_ms:.2f} ms")

            async def receive_transcripts():
                try:
                    async for message in ws:
                        print(f"Received message: {message.data}")
                        try:
                            response = json.loads(message.data)
                            if response.get("type") == "Results":
                                transcript = response["channel"]["alternatives"][0].get("transcript", "")
                                if transcript:
                                    print("Transcript:", transcript)
                            elif response.get("type") == "ClosedStream":
                                print("Received ClosedStream message")
                                break
                        except json.JSONDecodeError as e:
                            print(f"Error decoding JSON message: {e}")
                        except KeyError as e:
                            print(f"Key error: {e}")
                except Exception as e:
                    print(f"WebSocket error: {e}")

            await asyncio.gather(send_audio_stream(chunk_ms), receive_transcripts())

def main():
    parser = argparse.ArgumentParser(description="Stream audio to Deepgram for transcription.")
    parser.add_argument("wav_file", help="Path to the WAV file")
    parser.add_argument("--lang", default="en", help="Language code (default: en)")
    parser.add_argument("--blank_audio_ms_pre", type=int, default=0, help="Milliseconds of blank audio to prepend (default: 0)")
    parser.add_argument("--blank_audio_ms_post", type=int, default=0, help="Milliseconds of blank audio to append (default: 0)")
    parser.add_argument("--chunk_ms", type=int, default=250, help="Milliseconds of audio per chunk (default: 250)")
    parser.add_argument("--close_wait", type=int, default=2, help="Seconds to wait before sending CloseStream (default: 2)")
    
    args = parser.parse_args()

    asyncio.run(stream_audio_to_websocket(args.wav_file, args.lang, args.blank_audio_ms_pre, args.blank_audio_ms_post, args.chunk_ms, args.close_wait))

if __name__ == "__main__":
    main()
</pre></body></html>