You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Flutter与just_audio实现ElevenLabs音频流式播放?

实现ElevenLabs流式音频边下载边播放

问题根源

你当前的代码用http.post请求音频,这个方法会等待整个响应完全接收后才返回bodyBytes,所以必须等全部音频下载完才能播放,没法实现流式效果。要解决这个问题,需要直接处理API返回的字节流,而不是缓冲整个响应。

解决方案步骤

  1. 改用http.Client.send获取实时字节流:这个方法不会缓冲整个响应,而是返回一个Stream<List<int>>,每收到一块音频数据就会触发流事件。
  2. 适配just_audio的流式源:自定义StreamAudioSource来对接这个实时流,让播放器可以边接收数据边解码播放。
  3. 调整播放逻辑:直接将流式源传给音频播放器,无需等待全部数据加载完成。

修改后的完整代码

1. 获取音频流的函数

Stream<List<int>> _fetchAudioStream(String text) async* {
  final client = http.Client();
  try {
    final request = http.Request(
      'POST',
      Uri.parse('https://api.elevenlabs.io/v1/text-to-speech/${widget.voiceId}/stream'),
    );
    request.headers.addAll({
      'Content-Type': 'application/json',
      'xi-api-key': dotenv.env['ELEVENLABSKEY']!,
    });
    request.body = jsonEncode({
      "text": text.replaceAll('*', ''),
      "model_id": myModel,
      "voice_settings": widget.voiceSetting,
    });

    final response = await client.send(request);
    if (response.statusCode == 200) {
      // 直接转发API返回的字节流
      yield* response.stream;
    } else {
      throw Exception('请求失败,状态码: ${response.statusCode}');
    }
  } catch (e) {
    print('获取音频流错误: $e');
    rethrow;
  } finally {
    client.close();
  }
}

2. 适配实时流的自定义音频源

class ElevenLabsStreamSource extends StreamAudioSource {
  final Stream<List<int>> audioStream;
  final int? contentLength;

  ElevenLabsStreamSource(this.audioStream, [this.contentLength]);

  @override
  Future<StreamAudioResponse> request([int? start, int? end]) async {
    // ElevenLabs流式API不支持范围请求,所以忽略start/end参数
    return StreamAudioResponse(
      sourceLength: contentLength ?? -1, // 未知总长度时传入-1
      contentLength: -1,
      offset: start ?? 0,
      stream: audioStream,
      contentType: 'audio/mpeg',
    );
  }
}

3. 流式播放逻辑

void _playStreamingAudio(String text) async {
  try {
    // 获取实时音频流并创建流式源
    final audioStream = _fetchAudioStream(text);
    await _audioPlayer.setAudioSource(ElevenLabsStreamSource(audioStream));
    // 立即开始播放
    _audioPlayer.play();
  } catch (e) {
    print('播放错误: $e');
  }
}

额外说明

  • 如果需要实现队列播放,可以用ConcatenatingAudioSource将多个ElevenLabsStreamSource加入队列,播放器会自动按顺序播放。
  • 确保你的just_audio包是最新稳定版,旧版本可能对流式源的支持有问题。
  • 处理流中断的情况:比如网络断开时,流会抛出异常,需要在播放逻辑中捕获并处理(比如提示用户重新播放)。

内容的提问来源于stack exchange,提问作者Sahil Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:13:10