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

问题描述 投票:0回答:4

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

我正在ViewHolder内的RecyclerView Adapter的bind方法内实现ExoPlayer。

我正在使用的视频格式是m3u8,我正在使用的URL在浏览器中有效。所以我知道视频链接是有效的。我也在其中测试了一个youtube链接。

这是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:源错误。com.google.android.exoplayer2.source.UnrecognizedInputFormatException:没有可用的提取器(MatroskaExtractor,FragmentedMp4Extractor,Mp4Extractor,Mp3Extractor,AdtsExtractor,Ac3Extractor,TsExtractor,FlvExtractor,OggExtractor,PsExtractor,WavExtractor,AmrExtractor,Ac4Extractor,FlacExtractor)可以读取流。在com.google.android.exoplayer2.source.ProgressiveMediaPeriod $ ExtractorHolder.selectExtractor(ProgressiveMediaPeriod.java:1090)在com.google.android.exoplayer2.source.ProgressiveMediaPeriod $ ExtractingLoadable.load(ProgressiveMediaPeriod.java:969)在com.google.android.exoplayer2.upstream.Loader $ LoadTask.run(Loader.java:391)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:636)在java.lang.Thread.run(Thread.java:764)

我不确定我在做什么错,关于如何解决此问题的任何想法?

android android-recyclerview android-video-player exoplayer2.x
4个回答
1
投票

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

幸运的是,文件格式并不复杂,解析起来也不应该太困难。看来它已经被很好地证明了。维基百科上甚至有一些示例:https://en.wikipedia.org/wiki/M3U


1
投票

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

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);
}

1
投票

在Android 4.1+上,您可以使用此库https://github.com/brianwernick/ExoMedia/。自述页面上提到的示例应该足以使您入门。我已经复制了该代码段,并进行了一些补充/修改。

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();
        }

0
投票

您需要修改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 for DASH。
  • SsMediaSource用于SmoothStreaming。
  • 用于HLS的[HlsMediaSource(这是您的格式=> .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))
}
© www.soinside.com 2019 - 2024. All rights reserved.