Playing HLS video in app from Firebase Storage

113 Views Asked by At

I'm trying to play an HLS format video in Flutter, where the video is stored in Firebase Storage, and I'm using the Google Transcoder API to generate the HLS video.

1. I create the videos

enter image description here

Content of file_1708297675081_0f606403e29817ac9663.m3u8:

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=412476,AVERAGE-BANDWIDTH=404498,VIDEO-RANGE=SDR,FRAME-RATE=60,RESOLUTION=640x360,CODECS="avc1.64001e,mp4a.40.2"
hls.m3u8?alt=media

(I read that a possible issue might be the absence of ?alt=media so I manually added it to the file for testing purposes.)

hls.m3u8:

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-VERSION:4
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:6.020,
hls0000000000.ts?alt=media
#EXTINF:1.703,
hls0000000001.ts?alt=media
#EXT-X-ENDLIST

When attempting to play the video in Flutter, I tried both the file_1708297675081_0f606403e29817ac9663.m3u8 and hls.m3u8 files, both unsuccessfully.

For this, I generated a download URL using the Firebase SDK: https://firebasestorage.googleapis.com/v0/b/MYPROJECT.appspot.com/o/users%2Fajd5ZCUGKeMBktnk4W2ruVCG2Uj2%2FZXy2hO4WIwu5V1Qa9Evw%2Foptimized%2Fvideos%2Ffile_1708297675081_0f606403e29817ac9663.m3u8?alt=media&token=TOKEN

"MYPROJECT" and "TOKEN" are properly filled in. When I open the link in a browser, the page loads, but it does not allow the video to play (although I read this is likely a CORS issue, but regardless, it should work in the application.)

When I open link in browser (or just click m3u8 files on console):

enter image description here

In Flutter, I'm using the video_player package. I tried playing an openly accessible m3u8 file, and it was successful, so the Flutter code is fine.

The Flutter error message when I try to play my own file:

 I/flutter ( 8209): URL:
 https://firebasestorage.googleapis.com/v0/b/---myapp---.appspot.com/o/users%2Fajd5ZCUGKeMBktnk4W2ruVCG2Uj2%2FZXy2hO4WIwu5V1Qa9Evw%2Foptimized%2Fvideos%2Ffile_1708297675081_0f606403e29817ac9663.m3u8?alt=media&token=---token---
 I/ExoPlayerImpl( 8209): Init 94f5a88 [ExoPlayerLib/2.18.7] [emu64xa, sdk_gphone64_x86_64, Google, 34] I/Surface ( 8209):
 Surface::setFrameRate is deprecated, setFrameRate hint is dropped as
 destination is not SurfaceFlinger D/EGL_emulation( 8209):
 app_time_stats: avg=25.38ms min=6.67ms max=77.93ms count=36
 D/EGL_emulation( 8209): app_time_stats: avg=29.32ms min=11.05ms
>max=56.89ms count=32 D/EGL_emulation( 8209): app_time_stats:
 avg=27.87ms min=11.06ms max=43.51ms count=34 D/EGL_emulation( 8209):
>app_time_stats: avg=34.28ms min=12.12ms max=52.86ms count=29
>E/ExoPlayerImplInternal( 8209): Playback error
>E/ExoPlayerImplInternal( 8209):  
>com.google.android.exoplayer2.ExoPlaybackException: Source error
>E/ExoPlayerImplInternal( 8209):       at
com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:644)
E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:616)
 E/ExoPlayerImplInternal( 8209):       at
 android.os.Handler.dispatchMessage(Handler.java:102)
 E/ExoPlayerImplInternal( 8209):       at
 android.os.Looper.loopOnce(Looper.java:205) E/ExoPlayerImplInternal(
 8209):       at android.os.Looper.loop(Looper.java:294)
 E/ExoPlayerImplInternal( 8209):       at
 android.os.HandlerThread.run(HandlerThread.java:67)
 E/ExoPlayerImplInternal( 8209):   Caused by:
 com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException:
 Response code: 404 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:413)
 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:263)
 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
 E/ExoPlayerImplInternal( 8209):       at
com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:99)
 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.DataSourceInputStream.open(DataSourceInputStream.java:62)
 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.ParsingLoadable.load(ParsingLoadable.java:174)
 E/ExoPlayerImplInternal( 8209):       at
 com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
 E/ExoPlayerImplInternal( 8209):       at
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
 E/ExoPlayerImplInternal( 8209):       at
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
 E/ExoPlayerImplInternal( 8209):       at
 java.lang.Thread.run(Thread.java:1012) E/flutter ( 8209):
 [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled
 Exception: PlatformException(VideoError, Video player had error
 com.google.android.exoplayer2.ExoPlaybackException: Source error,
 null, null

)

I also tried to play hls0000000000.ts in browser, it SUCCESSFUL.

But I can't play m3u8 file in browser and flutter app. (But on browser maybe CORS problem and I don't want to change it.)

Rules not problem, because I allowed everything:

  service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read; allow write;
    }
  }
}

I really don't know where is the problem.. Flutter code good (can play m3u8 videos), maybe security or cors or token or m3u8 file faulty. I just now used first time transcoder API, so maybe m3u8 files also not correct. Thank you for help.

1

There are 1 best solutions below

0
Adrián Varga On

Solved!

I use this instruction: https://medium.com/p/411e4fff68fa

But I missed this important information:

Notice the line 1_fileSequence_0.ts. This is the relative path to the .ts chunk in the playlist. But when we upload this to a folder, it's missing the folder name from the URL. It's also missing the ?alt=media query parameter, that's required to get the actual file from Firebase, and not just the metadata.

So not just ?alt=media need, need folders (users/..../...ts?alt=media) too! (Every file is in same folder, but for m3u8 file need full addres, I don't thought that.)

Good m3u8 file:

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-VERSION:4
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:6.020,
users%2Fajd5ZCUGKeMBktnk4W2ruVCG2Uj2%2FZXy2hO4WIwu5V1Qa9Evw%2Foptimized%2Fvideos%2Fhls0000000000.ts?alt=media
#EXTINF:1.703,
users%2Fajd5ZCUGKeMBktnk4W2ruVCG2Uj2%2FZXy2hO4WIwu5V1Qa9Evw%2Foptimized%2Fvideos%2Fhls0000000001.ts?alt=media
#EXT-X-ENDLIST

And it's work.