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

如何播放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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:34:51