Recyclerview 中的 Exoplayer 错误,源错误没有可用的提取器
Posted
技术标签:
【中文标题】Recyclerview 中的 Exoplayer 错误,源错误没有可用的提取器【英文标题】:Exoplayer error in Recyclerview, Source error None of the available extractors 【发布时间】:2020-06-20 07:37:21 【问题描述】:我正在使用 ExoPlayer 在 RecyclerView 中流式传输视频。
我正在 ViewHolder 中的 RecyclerView Adapter 的绑定方法中实现 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)
我不确定我做错了什么,关于如何解决这个问题的任何想法?
【问题讨论】:
【参考方案1】:你需要修改你的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))
【讨论】:
【参考方案2】:我不认为 m3u8 是一种视频格式,而是一种播放列表格式。我认为 Exoplayer 比处理播放列表级别低;可能你需要自己阅读m3u8文件,然后自己传入播放列表中的链接。
幸运的是,文件格式并不复杂,解析起来也不难。它似乎有很好的记录。***上甚至还有一些例子:https://en.wikipedia.org/wiki/M3U
【讨论】:
【参考方案3】:在 Android 4.1+ 上,您可以使用这个库 https://github.com/brianwernick/ExoMedia/ 。自述页面上提到的示例应该足以让您入门。我已经复制了该代码 sn-p 并进行了一些添加/修改。
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();
【讨论】:
【参考方案4】:对于流式传输 .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);
【讨论】:
以上是关于Recyclerview 中的 Exoplayer 错误,源错误没有可用的提取器的主要内容,如果未能解决你的问题,请参考以下文章
如何用recyclerview和viewpager2实现exoplayer?
使用 exoplayer android 在 recyclerview 中显示视频
Exoplayer Recyclerview 第二次播放错误的视频