'Exoplayer - How to download a simple m3u8 file with ts chunks
Hi I'm trying to download a simple m3u8 video from a given URL using ExoPlayer and the DownloadService
the URL returns
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:16
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:13.733333,
q1080_0.ts
#EXTINF:8.333333,
q1080_1.ts
#EXTINF:8.333333,
q1080_2.ts
#EXTINF:15.533333,
q1080_3.ts
#EXT-X-ENDLIST
I tried using DownloadHelper like this
val downloadHelper: DownloadHelper = DownloadHelper.forMediaItem(
activity,
MediaItem.fromUri(Uri.parse(url)),
DefaultRenderersFactory(activity),
DefaultHttpDataSourceFactory())
downloadHelper.prepare(object : DownloadHelper.Callback {
override fun onPrepared(helper: DownloadHelper) { }
override fun onPrepareError(helper: DownloadHelper, e: IOException) { }
})
val buffer = ByteArray(1204)
val request = downloadHelper.getDownloadRequest(buffer) // <--- CRASH HERE
DownloadService.sendAddDownload(activity, HLSDownloaderService::class.java, request, false)
but it doesn't work. I'm getting the next error
2021-05-22 18:50:37.816 28929-28929/app.meedu.app E/MethodChannel#app.meedu.app/video-downloader: Failed to handle method call
java.lang.IllegalStateException
at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:84)
at com.google.android.exoplayer2.offline.DownloadHelper.assertPreparedWithMedia(DownloadHelper.java:827)
at com.google.android.exoplayer2.offline.DownloadHelper.getDownloadRequest(DownloadHelper.java:753)
at app.meedu.app.platform_channels.VideoDownloader.onMethodCall(VideoDownloader.kt:53)
at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:818)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2021-05-22 18:50:41.570 28929-29125/app.meedu.app E/VideoFrameReleaseHelper: Failed to call Surface.setFrameRate
java.lang.IllegalStateException: Surface has already been released.
at android.view.Surface.checkNotReleasedLocked(Surface.java:696)
at android.view.Surface.setFrameRate(Surface.java:905)
at com.google.android.exoplayer2.video.VideoFrameReleaseHelper.setSurfaceFrameRateV30(VideoFrameReleaseHelper.java:389)
at com.google.android.exoplayer2.video.VideoFrameReleaseHelper.clearSurfaceFrameRate(VideoFrameReleaseHelper.java:379)
at com.google.android.exoplayer2.video.VideoFrameReleaseHelper.onStopped(VideoFrameReleaseHelper.java:232)
at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onStopped(MediaCodecVideoRenderer.java:471)
at com.google.android.exoplayer2.BaseRenderer.stop(BaseRenderer.java:165)
at com.google.android.exoplayer2.ExoPlayerImplInternal.ensureStopped(ExoPlayerImplInternal.java:1599)
at com.google.android.exoplayer2.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:1608)
at com.google.android.exoplayer2.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:1351)
at com.google.android.exoplayer2.ExoPlayerImplInternal.stopInternal(ExoPlayerImplInternal.java:1314)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:494)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
Solution 1:[1]
you need to perform helper.getDownloadRequest inside onPrepared(helper: DownloadHelper) { }. And make sure you are using the helper that is passed into the callback, not the one you defined yourself!
here is my code from a working app
public static void downloadAsset(HLSAsset asset) {
MediaItem mediaItem = asset.getMediaItem();
DownloadHelper downloadHelper = DownloadHelper.forMediaItem(
context,
mediaItem,
null,
dataSourceFactory
);
downloadHelper.prepare(new DownloadHelper.Callback() {
@Override
public void onPrepared(DownloadHelper helper) {
DownloadRequest request = helper
.getDownloadRequest(
asset.id,
null
);
DownloadService.sendAddDownload(
context,
AssetDownloadService.class,
request,
false
);
}
@Override
public void onPrepareError(DownloadHelper helper, IOException e) {
Log.w(TAG, "Something happened");
}
});
}
and relevant HLSAsset bit
public class HLSAsset {
String id;
String hlsUrl;
...
MediaItem getMediaItem() {
return new MediaItem.Builder()
.setUri(hlsUrl)
.setStreamKeys(
Collections.singletonList(
new StreamKey(HlsMultivariantPlaylist.GROUP_INDEX_VARIANT, 0))
)
.setMimeType(MimeTypes.APPLICATION_M3U8)
.build();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jo Gro |
