我正在尝试在 Flutter 中播放 HLS 格式视频,该视频存储在 Firebase Storage 中,并且我正在使用 Google Transcoder API 生成 HLS 视频。
1。我制作视频
文件内容_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
(我读到可能的问题可能是缺少 ?alt=media,因此我手动将其添加到文件中以进行测试。)
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
尝试在 Flutter 中播放视频时,我尝试了 file_1708297675081_0f606403e29817ac9663.m3u8 和 hls.m3u8 文件,但均未成功。
为此,我使用 Firebase SDK 生成了一个下载 URL: https://firebasestorage.googleapis.com/v0/b/MYPROJECT.appspot.com/o/users%2Fajd5ZCUGKeMBktnk4W2ruVCG2Uj2%2FZXy2hO4WIwu5V1Qa9Evw%2Foptimized%2Fvideos%2Ffile_1708297675081_0f606403e2 9817ac9663.m3u8?alt=媒体&令牌=令牌
“MYPROJECT”和“TOKEN”已正确填写。当我在浏览器中打开链接时,页面会加载,但不允许播放视频(虽然我读到这可能是 CORS 问题,但无论如何,它应该在应用程序中工作。)
当我在浏览器中打开链接时(或只需单击控制台上的 m3u8 文件):
在 Flutter 中,我使用 video_player 包。我尝试播放一个可公开访问的 m3u8 文件,并且成功了,因此 Flutter 代码没有问题。
当我尝试播放自己的文件时出现 Flutter 错误消息:
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
)
我也尝试在浏览器中播放
hls0000000000.ts
,成功了。
但是我无法在浏览器和 flutter 应用程序中播放
m3u8
文件。 (但在浏览器上可能存在CORS
问题,我不想更改它。)
规则不是问题,因为我允许一切:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read; allow write;
}
}
}
我真的不知道问题出在哪里.. Flutter 代码良好(可以播放 m3u8 视频),可能是安全性、cors、令牌或 m3u8 文件有问题。我刚刚使用了第一次转码器 API,所以也许 m3u8 文件也不正确。 谢谢你的帮助。
解决了!
我使用这个指令: https://medium.com/p/411e4fff68fa
但是我错过了这个重要信息:
注意 1_fileSequence_0.ts 行。这是相对路径 播放列表中的 .ts 块。 但是当我们将其上传到文件夹时,它是 URL 中缺少文件夹名称。 它还缺少 ?alt=media 查询参数,需要从 Firebase 获取实际文件, 不仅仅是元数据。
所以不仅仅是 ?alt=media 需要,还需要文件夹 (users/..../...ts?alt=media)! (每个文件都在同一个文件夹中,但对于 m3u8 文件需要完整地址,我不这么认为。)
好的m3u8文件:
#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
这是工作。