> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getbifrost.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming Responses

> Receive AI responses in real-time as they're generated. Perfect for chat applications, audio processing, and real-time transcription where you want immediate results.

## Streaming Text Completion

Stream plain text completions as they are generated, ideal for autocomplete, summaries, and single-output generation.

```go theme={null}
stream, err := client.TextCompletionStreamRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), &schemas.BifrostTextCompletionRequest{
	Provider: schemas.OpenAI,
	Model:    "gpt-4o-mini",
	Input: &schemas.TextCompletionInput{
		PromptStr: bifrost.Ptr("A for apple and B for"),
	},
})

if err != nil {
	log.Printf("Streaming request failed: %v", err)
	return
}

for chunk := range stream {
	// Handle errors in stream
	if chunk.BifrostError != nil {
		log.Printf("Stream error: %v", chunk.BifrostError)
		break
	}

	// Process response chunks
	if chunk.BifrostTextCompletionResponse != nil && len(chunk.BifrostTextCompletionResponse.Choices) > 0 {
		choice := chunk.BifrostTextCompletionResponse.Choices[0]
		
		// Check for streaming content
		if choice.TextCompletionResponseChoice != nil &&
			choice.TextCompletionResponseChoice.Text != nil {
			content := *choice.BifrostTextCompletionResponseChoice.Text
			fmt.Print(content) // Print content as it arrives
		}
	}
}
```

## Streaming Chat Responses

Receive incremental chat deltas in real-time. Append delta content to progressively render assistant messages.

```go theme={null}
stream, err := client.ChatCompletionStreamRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), &schemas.BifrostChatRequest{
	Provider: schemas.OpenAI,
	Model:    "gpt-4o-mini",
	Input:    messages,
})

if err != nil {
	log.Printf("Streaming request failed: %v", err)
	return
}

for chunk := range stream {
	// Handle errors in stream
	if chunk.BifrostError != nil {
		log.Printf("Stream error: %v", chunk.BifrostError)
		break
	}

	// Process response chunks
	if chunk.BifrostChatResponse != nil && len(chunk.BifrostChatResponse.Choices) > 0 {
		choice := chunk.BifrostChatResponse.Choices[0]

		// Check for streaming content
		if choice.ChatStreamResponseChoice != nil &&
			choice.ChatStreamResponseChoice.Delta != nil &&
			choice.ChatStreamResponseChoice.Delta.Content != nil {

			content := *choice.ChatStreamResponseChoice.Delta.Content
			fmt.Print(content) // Print content as it arrives
		}
	}
}
```

> **Note:** Streaming requests also follow the default timeout setting defined in provider configuration, which defaults to **30 seconds**.

<Note>
  Bifrost standardizes all stream responses to send usage and finish reason only in the last chunk, and content in the previous chunks.
</Note>

## Responses API Streaming

Use the OpenAI-style Responses API with streaming for unified flows. Events arrive via SSE; accumulate text deltas until completion.

```go theme={null}
messages := []schemas.ResponsesMessage{
	{
		Role: bifrost.Ptr(schemas.ResponsesInputMessageRoleUser),
		Content: &schemas.ResponsesMessageContent{
			ContentStr: bifrost.Ptr("Hello, Bifrost!"),
		},
	},
}

stream, err := client.ResponsesStreamRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), &schemas.BifrostResponsesRequest{
	Provider: schemas.OpenAI,
	Model:    "gpt-4o-mini",
	Input:    messages,
})

if err != nil {
	log.Printf("Streaming request failed: %v", err)
	return
}

for chunk := range stream {
	// Handle errors in stream
	if chunk.BifrostError != nil {
		log.Printf("Stream error: %v", chunk.BifrostError)
		break
	}

	// Process response chunks
	if chunk.BifrostResponsesStreamResponse != nil {
		delta := chunk.BifrostResponsesStreamResponse.Delta

		// Check for streaming content
		if delta != nil {
			fmt.Print(*delta) // Print content as it arrives
		}
	}
}
```

## Text-to-Speech Streaming: Real-time Audio Generation

Stream audio generation in real-time as text is converted to speech. Ideal for long texts or when you need immediate audio playback.

```go theme={null}
stream, err := client.SpeechStreamRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), &schemas.BifrostSpeechRequest{
	Provider: schemas.OpenAI,
	Model:    "tts-1", // Using text-to-speech model
	Input: &schemas.SpeechInput{
		Input: "Hello! This is a sample text that will be converted to speech using Bifrost's speech synthesis capabilities. The weather today is wonderful, and I hope you're having a great day!",
	},
	Params: &schemas.SpeechParameters{
		VoiceConfig: &schemas.SpeechVoiceInput{
			Voice: schemas.Ptr("alloy"),
		},
		ResponseFormat: schemas.Ptr("mp3"),
	},
})

if err != nil {
	panic(err)
}

// Handle speech synthesis stream
var audioData []byte
var totalChunks int
filename := "output.mp3"

for chunk := range stream {
	if chunk.BifrostError != nil {
		panic(fmt.Sprintf("Stream error: %s", chunk.BifrostError.Error.Message))
	}

	if chunk.BifrostSpeechStreamResponse != nil {
		// Accumulate audio data from each chunk
		audioData = append(audioData, chunk.BifrostSpeechStreamResponse.Audio...)
		totalChunks++
		fmt.Printf("Received chunk %d, size: %d bytes\n", totalChunks, len(chunk.BifrostSpeechStreamResponse.Audio))
	}
}

if len(audioData) > 0 {
	// Save the accumulated audio to a file
	err := os.WriteFile(filename, audioData, 0644)
	if err != nil {
		panic(fmt.Sprintf("Failed to save audio file: %v", err))
	}

	fmt.Printf("Speech synthesis streaming complete! Audio saved to %s\n", filename)
	fmt.Printf("Total chunks received: %d, final file size: %d bytes\n", totalChunks, len(audioData))
}
```

## Speech-to-Text Streaming: Real-time Audio Transcription

Stream audio transcription results as they're processed. Get immediate text output for real-time applications or long audio files.

```go theme={null}
// Read the audio file for transcription
audioFilename := "output.mp3"
audioData, err := os.ReadFile(audioFilename)
if err != nil {
	panic(fmt.Sprintf("Failed to read audio file %s: %v. Please make sure the file exists.", audioFilename, err))
}

fmt.Printf("Loaded audio file %s (%d bytes) for transcription...\n", audioFilename, len(audioData))

stream, err := client.TranscriptionStreamRequest(schemas.NewBifrostContext(context.Background(), schemas.NoDeadline), &schemas.BifrostTranscriptionRequest{
	Provider: schemas.OpenAI,
	Model:    "whisper-1", // Using Whisper model for transcription
	Input: &schemas.TranscriptionInput{
		File: audioData,
	},
	Params: &schemas.TranscriptionParameters{
		Prompt: schemas.Ptr("This is a sample audio transcription from Bifrost speech synthesis."), // Optional: provide context
	},
})

if err != nil {
	panic(err)
}

for chunk := range stream {
	if chunk.BifrostError != nil {
		panic(fmt.Sprintf("Stream error: %s", chunk.BifrostError.Error.Message))
	}

	if chunk.BifrostTranscriptionStreamResponse != nil && chunk.BifrostTranscriptionStreamResponse.Delta != nil {
		// Print each chunk of text as it arrives
		fmt.Print(*chunk.BifrostTranscriptionStreamResponse.Delta)
	}
}
```

## Streaming Best Practices

### Buffering for Audio

For audio streaming, consider buffering chunks before saving:

```go theme={null}
const bufferSize = 1024 * 1024 // 1MB buffer

var audioBuffer bytes.Buffer
var lastSave time.Time

for chunk := range stream {
	if chunk.BifrostSpeechStreamResponse != nil {
		audioBuffer.Write(chunk.BifrostSpeechStreamResponse.Audio)

		// Save every second or when buffer is full
		if time.Since(lastSave) > time.Second || audioBuffer.Len() > bufferSize {
			// Append to file
			file, err := os.OpenFile("streaming_audio.mp3", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err == nil {
				file.Write(audioBuffer.Bytes())
				file.Close()
				audioBuffer.Reset()
				lastSave = time.Now()
			}
		}
	}
}
```

### Context and Cancellation

Use context to control streaming duration:

```go theme={null}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

stream, err := client.ChatCompletionStreamRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), &schemas.BifrostChatRequest{
	// ... your request
})

// Stream will automatically stop after 30 seconds
```

## Voice Options

OpenAI TTS supports these voices:

* `alloy` - Balanced, natural voice
* `echo` - Deep, resonant voice
* `fable` - Expressive, storytelling voice
* `onyx` - Strong, confident voice
* `nova` - Bright, energetic voice
* `shimmer` - Gentle, soothing voice

```go theme={null}
// Different voice example
VoiceConfig: schemas.SpeechVoiceInput{
    Voice: bifrost.Ptr("nova"),
},
```

> **Note:** Please check each model's documentation to see if it supports the corresponding streaming features. Not all providers support all streaming capabilities.

## Next Steps

* **[Tool Calling](./tool-calling)** - Enable AI to use external functions
* **[Multimodal AI](./multimodal)** - Process images and multimedia content
* **[Provider Configuration](./provider-configuration)** - Multiple providers for redundancy
* **[Core Features](../../features/)** - Advanced Bifrost capabilities
