如何播放本地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 代替,现在效果很好
我的任务是从服务器下载部分 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 代替,现在效果很好