VideoView的流媒体加载不足以缓冲

6
我的安卓应用程序在VideoView中在线播放视频。从文件播放视频时,它正常工作,甚至可以实时流式传输(使用m3u8);它始终从同一源流式传输,并且当我使用外部播放器/浏览器时,也可以正常流式传输(因此我不认为这是源的问题,该源类似于此文件:https://publish.dvlabs.com/democracynow/360/dn2016-0810.mp4
安卓监视器在崩溃之前记录了以下内容:
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

更准确地说,我的问题是:
  1. 我想知道这个错误 E/MediaPlayer: Error (1,-1004) 是什么(因为我在网上没有找到任何有关它的信息)。
  2. 如果像我怀疑的那样,基本上是文件/流结束错误,那么我希望能得到一些帮助,以缓冲或以其他方式加载视频,以避免这种情况发生?
我看到了这个问题: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,并且工作得很好。
  1. ExoPlayer添加为依赖项
  2. 在布局中更改视图为SimpleExoPlayerView
  3. 在Activity中初始化SimpleExoPlayer
  4. 初始化MediaSource并附加到播放器
  5. 不再需要时记得release()
有了这个,流媒体可以无缝地工作。

1
请使用 https://github.com/google/ExoPlayer。 - Qamar
是的...那就是解决方案。 - Nevermore
4个回答

1

Android MediaPlayer类不提供对缓冲区大小等低级设置的访问。

表单日志-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

当响应的实际数据小于预期字节数(通常在响应的内容长度头部中设置)时,FixedLengthInputStream会抛出该异常。请检查内容长度头部是否正确。(如果您为内容长度提供自己的值,请确保它是正确的。)
有关详细信息,请参见此帖子unexpected end of stream error
此外,这个也可以帮助您,请检查这个link,了解如何为MediaPlayer创建长时间缓冲区。

那最后一个链接带我到了ExoPlayer...那就是我需要的。 - Nevermore

0

在Android上,VideoView并不是最好的选择。如果你使用VLC,你会得到一个更流畅的视频缓冲体验。

以下是如何从源代码编译Android版VLC的说明:https://wiki.videolan.org/AndroidCompile/


0

在流媒体视频中使用VideoView可能会导致一些问题。我也遇到了很多问题。

使用JieCaoVideoPlayer库来流式传输视频。它提供了更多的可用选项。

https://github.com/lipangit/JieCaoVideoPlayer

只需导入它

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

是的,这很奇怪,但我们只需要代码,所以请忽略它。库非常适合流视频。 - Jaymin Panchal

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接