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))
}
所述
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))
}
我正在使用 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))
}
所述
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))
}