Flutter just_audio自定义MP3流播放卡顿问题求助
解决just_audio流式播放MP3卡顿、仅播放片段的问题
你当前的核心问题是每次收到HTTP流的分片数据就重新创建并设置音频源,相当于播放器每次只播放刚收到的一小段字节,自然只能听到片段且产生卡顿。下面是正确的实现方案:
1. 实现支持动态追加字节的自定义音频源
需要创建一个能持续积累字节、响应播放器数据请求的自定义源,而不是每次都生成新的源:
class StreamingMp3Source extends StreamAudioSource { final _accumulatedBytes = <int>[]; final _newBytesController = StreamController<List<int>>.broadcast(); // 向源中追加新收到的流数据 void appendBytes(List<int> bytes) { _accumulatedBytes.addAll(bytes); _newBytesController.add(bytes); } // 流数据接收完成后关闭控制器,避免内存泄漏 void finishStream() { _newBytesController.close(); } @override Future<StreamAudioResponse> request([int? start, int? end]) async { start ??= 0; end ??= _accumulatedBytes.length; // 如果播放器请求的范围超过当前已积累的字节,等待新数据到来 while (end > _accumulatedBytes.length) { await _newBytesController.stream.first; end = end! > _accumulatedBytes.length ? _accumulatedBytes.length : end; } return StreamAudioResponse( sourceLength: null, // 流式MP3无法提前获取总长度,设为null即可 contentLength: end - start, offset: start, stream: Stream.value(_accumulatedBytes.sublist(start, end)), contentType: 'audio/mpeg', ); } }
2. 修改HTTP请求与播放器逻辑
只需要初始化一次音频源,之后持续向这个源喂流数据即可:
// 初始化自定义源和播放器 final streamingSource = StreamingMp3Source(); await japlayer.setAudioSource(streamingSource, preload: false); await japlayer.play(); // 发送POST请求并处理流式响应 final request = http.Request( 'POST', Uri.parse("你的API地址"), ); request.bodyFields = {'xyz': 'abc'}; final streamedResponse = await request.send(); // 监听流数据,持续追加到自定义源 streamedResponse.stream.listen( (data) => streamingSource.appendBytes(data), onDone: () { streamingSource.finishStream(); // 可选:播放完成后停止播放器 // japlayer.stop(); }, onError: (error) { streamingSource.finishStream(); // 这里可以添加错误处理逻辑,比如提示用户播放失败 }, );
关键注意点
- 仅设置一次音频源:避免反复调用
setAudioSource打断播放流程 - 字节累加逻辑:通过维护一个全局字节列表,让播放器能读取到完整的流数据
- 等待新数据机制:当播放器请求的范围超出当前已积累的字节时,等待新数据到来再返回,保证播放连续性
- 流关闭处理:在HTTP流完成或出错时关闭控制器,防止内存泄漏
内容的提问来源于stack exchange,提问作者Chandan S Gowda
相关产品推荐
相关产品推荐

