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

ExoPlayer无法播放特定M3U8文件,报ERROR_CODE_IO_UNSPECIFIED错误

问题

  • 现有ExoPlayer实现可正常播放以下公开M3U8测试链接:
    1. https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8
    2. https://cph-p2p-msl.akamaized.net/hls/live/2000341/test/master.m3u8
  • 核心实现代码(Kotlin):
private fun initExo(url: String) {
    layoutVideoWidgetBinding!!.exoVideoPlayer.visible()
    layoutVideoWidgetBinding!!.loaderLa.gone()
    exoPlayer = ExoPlayer.Builder(layoutVideoWidgetBinding!!.root.context).build()
    exoPlayer?.playWhenReady = true
    layoutVideoWidgetBinding!!.exoVideoPlayer.player = exoPlayer

    val defaultHttpDataSourceFactory = DefaultHttpDataSource.Factory()
    val mediaItem = MediaItem.fromUri(url)
    val mediaSource =
        HlsMediaSource.Factory(defaultHttpDataSourceFactory).createMediaSource(mediaItem)


    exoPlayer?.apply {
        setMediaSource(mediaSource)
        seekTo(playbackPosition)
        playWhenReady = playWhenReady
        prepare()
        addListener(playbackStateListener)
    }
}
  • 无法播放自定义M3U8文件(该文件在VLC和网页端可正常播放),文件内容:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:138
#EXT-X-TARGETDURATION:2
#EXT-X-PLAYLIST-TYPE: EVENT
#EXTINF:1.796,
869409066980304_front-138.ts
#EXTINF:1.775,
869409066980304_front-139.ts
#EXTINF:1.772,
869409066980304_front-140.ts
#EXTINF:1.797,
869409066980304_front-141.ts
#EXTINF:1.783,
869409066980304_front-142.ts
#EXTINF:1.775,
869409066980304_front-143.ts
#EXTINF:1.161,
869409066980304_front-144.ts
#EXT-X-DISCONTINUITY
#EXTINF:1.894,
869409066980304_front-145.ts
#EXTINF:1.938,
869409066980304_front-146.ts
#EXTINF:1.668,
869409066980304_front-147.ts
#EXT-X-DISCONTINUITY
#EXTINF:1.241,
869409066980304_front-148.ts
#EXTINF:1.217,
869409066980304_front-149.ts
#EXTINF:1.153,
869409066980304_front-150.ts
#EXTINF:0.964,
869409066980304_front-151.ts
#EXT-X-DISCONTINUITY
#EXTINF:1.002,
869409066980304_front-152.ts
#EXT-X-DISCONTINUITY
#EXTINF:1.895,
869409066980304_front-153.ts
#EXTINF:1.133,
869409066980304_front-154.ts
#EXT-X-DISCONTINUITY
#EXTINF:0.000,
869409066980304_front-155.ts
#EXT-X-DISCONTINUITY
#EXTINF:1.839,
869409066980304_front-156.ts
#EXTINF:0.275,
869409066980304_front-157.ts
  • 报错信息:ExoPlayer抛出ERROR_CODE_IO_UNSPECIFIED错误,异常为androidx.media3.exoplayer.ExoPlaybackException: Source error
  • 播放状态日志仅打印STATE_BUFFERING,状态监听代码(Java):
@Override
public void onPlaybackStateChanged(@Player.State int playbackState) {
  if (playbackState == Player.STATE_ENDED) {
    showControls();
    Log.i("EventLogger", "STATE_ENDED");
  }
  if (playbackState == Player.STATE_BUFFERING) {
    Log.i("EventLogger", "STATE_BUFFERING");
  }
  if (playbackState == Player.STATE_IDLE) {
    Log.i("EventLogger", "STATE_IDLE");
  }
  if (playbackState == Player.STATE_READY) {
    Log.i("EventLogger", "STATE_READY");
  }
  if (playbackState == Player.EVENT_PLAYBACK_STATE_CHANGED) {
    Log.i("EventLogger", "EVENT_PLAYBACK_STATE_CHANGED");
  }
  updateButtonVisibility();
}

解决方案

1. 修复TS文件路径问题

你的M3U8中TS文件使用相对路径,ExoPlayer会基于M3U8的URL拼接TS文件请求地址,需确认:

  • M3U8与TS文件是否在同一域名/路径下,若不在,需将TS路径改为绝对URL
  • 服务器是否能正确解析相对路径的请求,必要时调整服务器路由配置

2. 处理EXT-X-DISCONTINUITY标签兼容

M3U8中大量存在该标签,需确保:

  • 每个不连续点前后的TS文件编码参数(分辨率、码率、编码格式)一致,避免ExoPlayer切换失败
  • 配置HlsMediaSource工厂开启兼容:
val hlsFactory = HlsMediaSource.Factory(defaultHttpDataSourceFactory)
    .setAllowChunklessPreparation(true)
val mediaSource = hlsFactory.createMediaSource(mediaItem)

3. 优化HttpDataSource配置

针对ERROR_CODE_IO_UNSPECIFIED网络类错误,调整数据源参数:

val defaultHttpDataSourceFactory = DefaultHttpDataSource.Factory()
    .setConnectTimeoutMs(10000)
    .setReadTimeoutMs(10000)
    .setAllowCrossProtocolRedirects(true)
    .setRetryCount(3)
// 若服务器需要鉴权Header,添加以下配置
defaultHttpDataSourceFactory.setDefaultRequestProperties(mapOf(
    "Authorization" to "Bearer your_token",
    "User-Agent" to "ExoPlayer/1.2.1"
))

4. 添加详细错误监听

当前监听未捕获错误事件,需补充onPlayerError方法定位具体问题:

private val playbackStateListener = object : Player.Listener {
    override fun onPlaybackStateChanged(playbackState: Int) {
        // 原有状态监听逻辑
    }

    override fun onPlayerError(error: PlaybackException) {
        Log.e("ExoPlayerError", "错误码: ${error.errorCode}, 信息: ${error.message}", error)
        error.cause?.let {
            Log.e("ExoPlayerErrorCause", "底层原因: ${it.message}", it)
        }
    }
}

5. 修正非法EXTINF值

M3U8中存在#EXTINF:0.000,的片段,违反HLS规范(EXTINF值需大于0),需修改该片段的EXTINF值为有效时长,或移除该片段。

6. 更新ExoPlayer版本

确保使用最新稳定版Media3(ExoPlayer),旧版本可能存在HLS特性支持缺陷:

implementation "androidx.media3:media3-exoplayer:1.2.1"
implementation "androidx.media3:media3-exoplayer-hls:1.2.1"
implementation "androidx.media3:media3-ui:1.2.1"

内容的提问来源于stack exchange,提问作者Tehleel Mir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:29:54