Recyclerview 中的 Exoplayer 错误,可用提取器的源错误 None

Exoplayer error in Recyclerview, Source error None of the available extractors

我正在使用 ExoPlayer 在 RecyclerView 中流式传输视频。

我正在我的 ViewHolder 中的 RecyclerView 适配器的绑定方法中实现 ExoPlayer。

我使用的视频格式是 m3u8,我使用的 URL 可以在浏览器中使用。 所以我知道视频 link 是有效的。我还在里面测试了一个 youtube link。

这是来自 Recyclerview 适配器的 ViewHolder 的代码 ->

class ViewHolder private constructor(val binding: FeedRowBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(context: Activity){
        if (entity.content.videolink != null) {
            setupVideoPlayer(entity.content.videolink, context)
        }
    }
}

private fun setupVideoPlayer(url: String, context: Activity) {
    val videoExoPlayer = SimpleExoPlayer.Builder(binding.videoView.context).build()
    videoExoPlayer.prepare(createUrlMediaSource(url, context))

    binding.play.setOnClickListener {
        videoExoPlayer.playWhenReady = true
    }

    binding.pause.setOnClickListener {
        videoExoPlayer.playWhenReady = false
    }
}

private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
    val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
    return ProgressiveMediaSource
           .Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
           .createMediaSource(Uri.parse(url))
}

当加载我的 recyclerview 并到达视频行时,我收到以下错误:

ExoPlayerImplInternal: Source error. com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (MatroskaExtractor, FragmentedMp4Extractor, Mp4Extractor, Mp3Extractor, AdtsExtractor, Ac3Extractor, TsExtractor, FlvExtractor, OggExtractor, PsExtractor, WavExtractor, AmrExtractor, Ac4Extractor, FlacExtractor) could read the stream. at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractorHolder.selectExtractor(ProgressiveMediaPeriod.java:1090) at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:969) at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:391) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at java.lang.Thread.run(Thread.java:764)

我不确定我做错了什么,关于如何解决这个问题有什么想法吗?

我不认为 m3u8 是一种视频格式,而是一种播放列表格式。我认为 Exoplayer 的级别低于处理播放列表;可能你需要自己阅读m3u8文件,然后自己传入播放列表中的链接。

幸运的是文件格式并不复杂,解析起来应该不会太困难。它似乎有据可查。维基百科上什至有一些例子:https://en.wikipedia.org/wiki/M3U

对于流式传输 .m3u8 文件,在初始化 Exoplayer 时使用以下代码:-

BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();

TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);

TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

videoPlayer = ExoPlayerFactory.newSimpleInstance(context,trackSelector);

Handler mHandler = new Handler();

String userAgent = Util.getUserAgent(context, "Exo Player");

DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(
                userAgent, null,
                DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
                1800000,
                true);

HlsMediaSource mediaSource = new HlsMediaSource(Uri.parse(mediaUrl),dataSourceFactory, 1800000,mHandler, null);

if (mediaUrl != null) {
    videoPlayer.prepare(mediaSource);
    videoPlayer.setPlayWhenReady(true);
}

在 Android 4.1+ 上,您可以使用此库 https://github.com/brianwernick/ExoMedia/。自述文件页面中提到的示例应该足以帮助您入门。我用一些 additions/modifications.

复制了该代码片段
private void setupVideoView() {
            EMVideoView emVideoView = (EMVideoView)findViewById(R.id.video_play_activity_video_view);
            emVideoView.setOnPreparedListener(this);

            //Enter your m3u8 URL below
            emVideoView.setVideoURI(Uri.parse("http://SOMESERVER/playlist.m3u8"));
        }

        @Override
        public void onPrepared(MediaPlayer mp) {
            //Starts the video playback as soon as it is ready
            emVideoView.start();
        }

        @Override
        public void onPause() {
            super.onPause();
            //Pause Video Playback
            emVideoView.pause();
        }

您需要修改您的createUrlMediaSource

private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
    val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
    return ProgressiveMediaSource
           .Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
           .createMediaSource(Uri.parse(url))
}

https://exoplayer.dev

所述
  • DashMediaSource 用于 DASH。
  • SsMediaSource 用于 SmoothStreaming。
  • HlsMediaSource 用于 HLS(这是您的格式 => .m3u8)。
  • ProgressiveMediaSource 用于常规媒体文件。

因此您需要将函数替换为:

private fun createUrlMediaSource(url: String, context: Activity): MediaSource {
    val userAgent = Util.getUserAgent(context, context.getString(R.string.about))
    return HlsMediaSource
           .Factory(DefaultDataSourceFactory(context, userAgent), DefaultExtractorsFactory())
           .createMediaSource(Uri.parse(url))
}