VideoView 流加载缓冲不足
VideoView Stream load not buffering enough
我的 android 应用程序在 VideoView
中在线播放视频。从文件播放视频时,它工作正常,甚至可以直播(m3u8
);它总是从同一个源流式传输,当我使用外部 player/browser 时,它同样可以很好地流式传输(所以我认为这不是源的问题,它是这样一个文件的变体:https://publish.dvlabs.com/democracynow/360/dn2016-0810.mp4
Android 监视器在崩溃前记录了这一点:
10-13 12:02:56.204 32460-32748/com.workingagenda.democracydroid D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= stagefright/1.2 (Linux;Android 6.0.1)
10-13 12:02:56.205 32460-32472/com.workingagenda.democracydroid D/MediaHTTPConnection: proxy null port 0
10-13 12:02:57.904 32460-32460/com.workingagenda.democracydroid D/MediaPlayer: getMetadata
10-13 12:02:58.438 32460-377/com.workingagenda.democracydroid W/MediaPlayer: info/warning (3, 0)
然后当它崩溃时我得到这些日志:
10-13 12:05:33.812 32460-32472/com.workingagenda.democracydroid W/MediaHTTPConnection: readAt 26869519 / 241 => java.net.ProtocolException: unexpected end of stream
10-13 12:08:32.480 32460-3546/com.workingagenda.democracydroid E/MediaPlayer: error (1, -1004)
10-13 12:08:32.480 32460-32460/com.workingagenda.democracydroid E/MediaPlayer: Error (1,-1004)
10-13 12:08:32.481 32460-32460/com.workingagenda.democracydroid D/VideoView: Error: 1,-1004
[ 10-13 12:08:32.512 5066: 453 E/ ]
Destroy C2D instance
[ 10-13 12:08:32.512 5066: 453 E/ ]
Destroy C2D instance
10-13 12:08:32.635 32460-32472/com.workingagenda.democracydroid E/MediaPlayer: error (1, -1004)
10-13 12:08:32.668 32460-32460/com.workingagenda.democracydroid E/MediaPlayer: Error (1,-1004)
10-13 12:08:32.668 32460-32460/com.workingagenda.democracydroid D/VideoView: Error: 1,-1004
更准确地说我的问题:
- 我想知道这个错误
E/MediaPlayer: Error (1,-1004)
是什么(因为我没有在网上找到任何关于它的信息)。
- 如果这是我怀疑的,基本上是 file/stream 错误的结尾,那么我希望得到一些帮助 缓冲或以其他方式加载视频以避免这种情况?
我看过这个问题,Android Streaming with MediaPlayer: Error(1, -1004) and 3GPP video,但答案没有太大帮助。
我找到了一个函数,MediaPlayer.prepareAsync()
,在这里 https://developer.android.com/reference/android/media/MediaPlayer.html#prepareAsync(),当 VideoView
打开视频时会自动调用它,但这似乎不起作用。
编辑
所以这个解决方案让我想到了 Google 的 ExoPlayer,它很容易换成我的 VideoView,而且效果很好。
- 添加 ExoPlayer 作为依赖项
- 将布局视图更改为
SimpleExoPlayerView
- 在Activity
中初始化SimpleExoPlayer
- 初始化
MediaSource
并附加到播放器
- 记得在不需要的时候
release()
。
有了它,流式传输就可以无缝工作了。
Android 上的 VideoView 不是最好的,如果您使用 VLC,您将获得更流畅的缓冲视频体验。
以下是有关如何从 Android 的源代码编译 VLC 的说明:https://wiki.videolan.org/AndroidCompile/
在流式视频中使用 VideoView
有时可能会出现问题。我也遇到了很多问题。
使用 JieCaoVideoPlayer 库进行流式传输 Video
。它允许更多可用选项。
导入即可
compile 'fm.jiecao:jiecaovideoplayer:5.3'
像普通视图一样添加布局
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="200dp"/>
设置URL你想玩的
JCVideoPlayerStandard jcVideoPlayerStandard = (JCVideoPlayerStandard) findViewById(R.id.videoplayer);
jcVideoPlayerStandard.setUp("http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4"
, JCVideoPlayerStandard.SCREEN_LAYOUT_NORMAL, "Video");
jcVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
Android MediaPlayer class 不提供对缓冲区大小等较低级别设置的访问。
形式日志-1004表示: public static final int MEDIA_ERROR_IO
对我来说这段代码工作正常:
try{
MediaController mediaController = new MediaController(this);
Uri video = Uri.parse(url);
mediaController.setAnchorView(videoView);
videoView.requestFocus();
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.setOnPreparedListener(new OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer arg0)
{
videoView.start();
}
});
}catch (Exception e) {
e.printStackTrace();
}
这似乎与流的来源有关,因为某些来源最终在设备上播放,但我们需要的那个从未播放过。
如果您能看到,那么您可以通过日志知道您的流存在问题。
MediaHTTPConnection: readAt 26869519 / 241 => java.net.ProtocolException: unexpected end of stream
当预期的字节数(通常在响应的 content-length header 中设置)大于响应中的实际数据时,FixedLengthInputStream 会抛出该异常。检查 content-length header 是否正确。 (如果您为内容长度提供自己的值,请确保它是正确的。)
更多详情请看这里postunexpected end of stream error
其他这个也对你有帮助,请检查这个link如何为 MediaPlayer 创建长时间缓冲区
implementation 'android.arch.lifecycle:extensions:1.1.0'
implementation 'android.arch.lifecycle:compiler:1.1.0'
implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
<cn.jzvd.JzvdStd
android:id="@+id/video_player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
JzvdStd jzvdStd;
jzvdStd = (JzvdStd) findViewById(R.id.video_player);
jzvdStd.setUp(getIntent().getExtras().getString("id"), getIntent().getExtras().getString("title"), 0);
jzvdStd.setScreenFullscreen();
jzvdStd.backButton.setVisibility(View.GONE);
jzvdStd.batteryLevel.setVisibility(View.GONE);
jzvdStd.batteryTimeLayout.setVisibility(View.GONE);
jzvdStd.titleTextView.setVisibility(View.GONE);
jzvdStd.dismissBrightnessDialog();
jzvdStd.dismissVolumeDialog();
jzvdStd.dissmissControlView();
jzvdStd.dismissProgressDialog();
jzvdStd.startVideo();
Glide.with(jzvdStd.getContext()).load(getIntent().getExtras().getString("thumb")).into(jzvdStd.thumbImageView);
@Override
public void onBackPressed() {
if (Jzvd.backPress()) {
super.onBackPressed();
return;
}
super.onBackPressed();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
Jzvd.releaseAllVideos();
}
我的 android 应用程序在 VideoView
中在线播放视频。从文件播放视频时,它工作正常,甚至可以直播(m3u8
);它总是从同一个源流式传输,当我使用外部 player/browser 时,它同样可以很好地流式传输(所以我认为这不是源的问题,它是这样一个文件的变体:https://publish.dvlabs.com/democracynow/360/dn2016-0810.mp4
Android 监视器在崩溃前记录了这一点:
10-13 12:02:56.204 32460-32748/com.workingagenda.democracydroid D/MediaHTTPConnection: filterOutInternalHeaders: key=User-Agent, val= stagefright/1.2 (Linux;Android 6.0.1)
10-13 12:02:56.205 32460-32472/com.workingagenda.democracydroid D/MediaHTTPConnection: proxy null port 0
10-13 12:02:57.904 32460-32460/com.workingagenda.democracydroid D/MediaPlayer: getMetadata
10-13 12:02:58.438 32460-377/com.workingagenda.democracydroid W/MediaPlayer: info/warning (3, 0)
然后当它崩溃时我得到这些日志:
10-13 12:05:33.812 32460-32472/com.workingagenda.democracydroid W/MediaHTTPConnection: readAt 26869519 / 241 => java.net.ProtocolException: unexpected end of stream
10-13 12:08:32.480 32460-3546/com.workingagenda.democracydroid E/MediaPlayer: error (1, -1004)
10-13 12:08:32.480 32460-32460/com.workingagenda.democracydroid E/MediaPlayer: Error (1,-1004)
10-13 12:08:32.481 32460-32460/com.workingagenda.democracydroid D/VideoView: Error: 1,-1004
[ 10-13 12:08:32.512 5066: 453 E/ ]
Destroy C2D instance
[ 10-13 12:08:32.512 5066: 453 E/ ]
Destroy C2D instance
10-13 12:08:32.635 32460-32472/com.workingagenda.democracydroid E/MediaPlayer: error (1, -1004)
10-13 12:08:32.668 32460-32460/com.workingagenda.democracydroid E/MediaPlayer: Error (1,-1004)
10-13 12:08:32.668 32460-32460/com.workingagenda.democracydroid D/VideoView: Error: 1,-1004
更准确地说我的问题:
- 我想知道这个错误
E/MediaPlayer: Error (1,-1004)
是什么(因为我没有在网上找到任何关于它的信息)。 - 如果这是我怀疑的,基本上是 file/stream 错误的结尾,那么我希望得到一些帮助 缓冲或以其他方式加载视频以避免这种情况?
我看过这个问题,Android Streaming with MediaPlayer: Error(1, -1004) and 3GPP video,但答案没有太大帮助。
我找到了一个函数,MediaPlayer.prepareAsync()
,在这里 https://developer.android.com/reference/android/media/MediaPlayer.html#prepareAsync(),当 VideoView
打开视频时会自动调用它,但这似乎不起作用。
编辑
所以这个解决方案让我想到了 Google 的 ExoPlayer,它很容易换成我的 VideoView,而且效果很好。
- 添加 ExoPlayer 作为依赖项
- 将布局视图更改为
SimpleExoPlayerView
- 在Activity 中初始化
- 初始化
MediaSource
并附加到播放器 - 记得在不需要的时候
release()
。
SimpleExoPlayer
有了它,流式传输就可以无缝工作了。
Android 上的 VideoView 不是最好的,如果您使用 VLC,您将获得更流畅的缓冲视频体验。
以下是有关如何从 Android 的源代码编译 VLC 的说明:https://wiki.videolan.org/AndroidCompile/
在流式视频中使用 VideoView
有时可能会出现问题。我也遇到了很多问题。
使用 JieCaoVideoPlayer 库进行流式传输 Video
。它允许更多可用选项。
导入即可
compile 'fm.jiecao:jiecaovideoplayer:5.3'
像普通视图一样添加布局
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/videoplayer"
android:layout_width="match_parent"
android:layout_height="200dp"/>
设置URL你想玩的
JCVideoPlayerStandard jcVideoPlayerStandard = (JCVideoPlayerStandard) findViewById(R.id.videoplayer);
jcVideoPlayerStandard.setUp("http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4"
, JCVideoPlayerStandard.SCREEN_LAYOUT_NORMAL, "Video");
jcVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
Android MediaPlayer class 不提供对缓冲区大小等较低级别设置的访问。
形式日志-1004表示: public static final int MEDIA_ERROR_IO
对我来说这段代码工作正常:
try{
MediaController mediaController = new MediaController(this);
Uri video = Uri.parse(url);
mediaController.setAnchorView(videoView);
videoView.requestFocus();
videoView.setMediaController(mediaController);
videoView.setVideoURI(video);
videoView.setOnPreparedListener(new OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer arg0)
{
videoView.start();
}
});
}catch (Exception e) {
e.printStackTrace();
}
这似乎与流的来源有关,因为某些来源最终在设备上播放,但我们需要的那个从未播放过。
如果您能看到,那么您可以通过日志知道您的流存在问题。
MediaHTTPConnection: readAt 26869519 / 241 => java.net.ProtocolException: unexpected end of stream
当预期的字节数(通常在响应的 content-length header 中设置)大于响应中的实际数据时,FixedLengthInputStream 会抛出该异常。检查 content-length header 是否正确。 (如果您为内容长度提供自己的值,请确保它是正确的。)
更多详情请看这里postunexpected end of stream error
其他这个也对你有帮助,请检查这个link如何为 MediaPlayer 创建长时间缓冲区
implementation 'android.arch.lifecycle:extensions:1.1.0'
implementation 'android.arch.lifecycle:compiler:1.1.0'
implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
<cn.jzvd.JzvdStd
android:id="@+id/video_player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
JzvdStd jzvdStd;
jzvdStd = (JzvdStd) findViewById(R.id.video_player);
jzvdStd.setUp(getIntent().getExtras().getString("id"), getIntent().getExtras().getString("title"), 0);
jzvdStd.setScreenFullscreen();
jzvdStd.backButton.setVisibility(View.GONE);
jzvdStd.batteryLevel.setVisibility(View.GONE);
jzvdStd.batteryTimeLayout.setVisibility(View.GONE);
jzvdStd.titleTextView.setVisibility(View.GONE);
jzvdStd.dismissBrightnessDialog();
jzvdStd.dismissVolumeDialog();
jzvdStd.dissmissControlView();
jzvdStd.dismissProgressDialog();
jzvdStd.startVideo();
Glide.with(jzvdStd.getContext()).load(getIntent().getExtras().getString("thumb")).into(jzvdStd.thumbImageView);
@Override
public void onBackPressed() {
if (Jzvd.backPress()) {
super.onBackPressed();
return;
}
super.onBackPressed();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
Jzvd.releaseAllVideos();
}