如何播放本地m3u8文件?

How to play local m3u8 files?

我的任务是从服务器下载部分 HLS 流并在 android 应用程序中本地播放。

我已经下载了所需的 .ts 块并形成了播放列表:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:10.000000,
/storage/emulated/0/Android/data/com.example.myapp/files/savedMovies/chunk0.ts
#EXTINF:10.000000,
/storage/emulated/0/Android/data/com.example.myapp/files/savedMovies/chunk1.ts
#EXTINF:10.000000,
/storage/emulated/0/Android/data/com.example.myapp/files/savedMovies/chunk2.ts
#EXTINF:10.000000,
/storage/emulated/0/Android/data/com.example.myapp/files/savedMovies/chunk3.ts
#EXT-X-ENDLIST

接下来,我已将 link 播放列表传递给 android.media.MediaPlayer 实例:

String fileLink = "/storage/emulated/0/Android/data/com.example.myapp/files/savedMovies/savedPlaylist.ts";
mediaPlayer.setDataSource(fileLink);

结果我收到了这样的异常:

W/System.err: java.io.IOException: Prepare failed.: status=0x1    
W/System.err:     at android.media.MediaPlayer._prepare(Native Method)    
W/System.err:     at android.media.MediaPlayer.prepare(MediaPlayer.java:1408)    
W/System.err:     at com.example.myapp.MainActivity.surfaceCreated(MainActivity.java:305)    
W/System.err:     at android.view.SurfaceView.updateWindow(SurfaceView.java:656)    
W/System.err:     at android.view.SurfaceView.onPreDraw(SurfaceView.java:172)    
W/System.err:     at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:1013)    
W/System.err:     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2542)    
W/System.err:     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1537)    
W/System.err:     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)    
W/System.err:     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:959)    
W/System.err:     at android.view.Choreographer.doCallbacks(Choreographer.java:734)    
W/System.err:     at android.view.Choreographer.doFrame(Choreographer.java:670)    
W/System.err:     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:945)    
W/System.err:     at android.os.Handler.handleCallback(Handler.java:751)    
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)    
W/System.err:     at android.os.Looper.loop(Looper.java:154)    
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6776)    
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)    
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)    
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408) 

如果我将原始服务器的播放列表保存在本地(使用 http links 到块)传递给播放器文件的路径,也会发生同样的事情

我试过在VLC播放器中播放本地文件:

intent.setDataAndType(Uri.parse(fileUrl), "video/m3u8");

但也会导致错误(本地和 http links)

谁能帮我解决这个问题?

我已经检查过权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

我的代码:

private void playVideo(String fileUrl) {
    surfaceView.setVisibility(View.VISIBLE);

    this.fileUrl = fileUrl;

    holder = surfaceView.getHolder();
    holder.addCallback(this);
}

@Override
public void onPrepared(MediaPlayer player) {
    mediaPlayer.start();
}


@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mediaPlayer = new MediaPlayer();

        File file = new File(fileUrl);
        FileInputStream inputStream = new FileInputStream(file);
        mediaPlayer.reset();
        mediaPlayer.setDataSource(inputStream.getFD());
        inputStream.close();

        mediaPlayer.setDisplay(holder);

        mediaPlayer.prepare();

        mediaPlayer.setOnErrorListener(this);
        mediaPlayer.setOnBufferingUpdateListener(this);
        mediaPlayer.setOnCompletionListener(this);
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.setOnVideoSizeChangedListener(this);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    } catch (IOException e) {
        e.printStackTrace();
    }
}


@Override
public void onPrepared(MediaPlayer player) {
    mediaPlayer.start();
}

据我所知,MediaPlayer 无法播放本地 m3u8 文件。

我用 ExoPlayer 代替,现在效果很好