如何播放Stream<List<int>>格式音频?YouTube视频音频播放报错求助
尝试从YouTube获取视频后,通过自定义StreamAudioSource子类播放音频,编写的代码如下:
class MyCustomSource extends StreamAudioSource { final List<int> bytes; MyCustomSource(this.bytes); @override Future<StreamAudioResponse> request([int? start, int? end]) async { start ??= 0; end ??= bytes.length; return StreamAudioResponse( sourceLength: bytes.length, contentLength: end - start, offset: start, stream: Stream.value(bytes.sublist(start, end)), contentType: 'video/mp4', ); } } var get = await videoUrl.first; var getAsUInt8List = Uint8List.fromList(get); AudioPlayer player = AudioPlayer(); await player.setAudioSource(MyCustomSource(getAsUInt8List)); player.play();
执行后出现以下错误日志:
E/ExoPlayerImplInternal( 5995): at com.google.android.exoplayer2.extractor.mp4.Mp4Extractor.read(Mp4Extractor.java:254)
E/ExoPlayerImplInternal( 5995): at com.google.android.exoplayer2.source.BundledExtractorsAdapter.read(BundledExtractorsAdapter.java:127)
E/ExoPlayerImplInternal( 5995): at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1039)
E/ExoPlayerImplInternal( 5995): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
E/ExoPlayerImplInternal( 5995): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
E/ExoPlayerImplInternal( 5995): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
E/ExoPlayerImplInternal( 5995): at java.lang.Thread.run(Thread.java:764)
E/AudioPlayer( 5995): TYPE_SOURCE: null
I/ExoPlayerImpl( 5995): Release 2b7745 [ExoPlayerLib/2.18.7] [generic_x86, Android SDK built for x86, Google, 27] [goog.exo.core, goog.exo.exoplayer, goog.exo.decoder, goog.exo.datasource, goog.exo.extractor]
I/flutter ( 5995): err : (0) Source error
尝试过其他音频服务仍无法解决问题,求正确播放Stream<List<int>>格式音频并解决当前报错的方法。
修正Content-Type参数
当前代码将contentType设为video/mp4,但播放的是音频流,需设置对应音频格式的MIME类型,比如AAC用audio/aac,MP3用audio/mpeg。可先通过工具检测字节流的实际编码格式,再配置正确类型。正确处理范围请求边界
ExoPlayer会发起分段加载的范围请求,需确保request方法处理参数时不越界:@override Future<StreamAudioResponse> request([int? start, int? end]) async { final clampedStart = (start ?? 0).clamp(0, bytes.length); final clampedEnd = (end ?? bytes.length).clamp(clampedStart, bytes.length); return StreamAudioResponse( sourceLength: bytes.length, contentLength: clampedEnd - clampedStart, offset: clampedStart, stream: Stream.value(Uint8List.fromList(bytes.sublist(clampedStart, clampedEnd))), contentType: 'audio/aac', // 替换为实际音频MIME类型 ); }验证字节流完整性与类型
从YouTube获取的字节流可能包含视频轨道或不完整,可先将字节流保存为本地文件,用媒体播放器测试是否为可播放的纯音频流。如果是带视频的MP4文件,需先分离出音频轨道再传入播放器。简化代码:使用现成的BytesAudioSource
若自定义StreamAudioSource易出问题,可直接使用audio_player库提供的BytesAudioSource(需确保库版本支持):await player.setAudioSource(BytesAudioSource(getAsUInt8List, contentType: 'audio/aac'));添加错误监听获取详细信息
给播放器添加错误监听,获取更具体的错误原因:player.onPlayerError.listen((error) { print('错误详情: ${error.message}, 错误码: ${error.code}'); });
内容的提问来源于stack exchange,提问作者smmm

