我有一个AES 128位加密的m3u8播放列表。我试着主持这个节目,
通过Cloudflare
播放列表在HTML5网络播放器上工作。然后我尝试在安卓应用程序中播放m3u8文件。我试过,一个颤振应用程序,一个反应本地应用程序和一个原生Java应用程序
我已经尝试了几乎所有的HLS库可用的颤振和反应本土化。但最后,每个玩家在谷歌ExoPlayer上都表现出了同样的错误。我已经试着修了差不多一个月了。我已经检查了大部分的吉特布问题,但没有运气。
这是我看到的错误(复制自颤振终端,但RN和本机java应用程序也显示了相同的错误)。
Restarted application in 4,802ms.
I/ExoPlayerImpl(25099): Release 2354449 [ExoPlayerLib/2.13.1] [m21, SM-M215F, samsung, 30] [goog.exo.core, goog.exo.hls]
I/ExoPlayerImpl(25099): Init 91918d7 [ExoPlayerLib/2.13.1] [m21, SM-M215F, samsung, 30]
6
I/System.out(25099): (HTTPLog)-Static: isSBSettingEnabled false
E/ExoPlayerImplInternal(25099): Playback error
E/ExoPlayerImplInternal(25099): com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:579)
E/ExoPlayerImplInternal(25099): at android.os.Handler.dispatchMessage(Handler.java:102)
E/ExoPlayerImplInternal(25099): at android.os.Looper.loop(Looper.java:246)
E/ExoPlayerImplInternal(25099): at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal(25099): Caused by: com.google.android.exoplayer2.ParserException: Cannot find sync byte. Most likely not a Transport Stream.
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.extractor.ts.TsExtractor.findEndOfFirstTsPacketInBuffer(TsExtractor.java:453)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.extractor.ts.TsExtractor.read(TsExtractor.java:320)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.source.hls.BundledHlsMediaChunkExtractor.read(BundledHlsMediaChunkExtractor.java:67)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.source.hls.HlsMediaChunk.feedDataToExtractor(HlsMediaChunk.java:434)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.source.hls.HlsMediaChunk.loadMedia(HlsMediaChunk.java:404)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.source.hls.HlsMediaChunk.load(HlsMediaChunk.java:355)
E/ExoPlayerImplInternal(25099): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
E/ExoPlayerImplInternal(25099): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/ExoPlayerImplInternal(25099): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/ExoPlayerImplInternal(25099): at java.lang.Thread.run(Thread.java:923)
E/flutter (25099): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: PlatformException(VideoError, Video player had error com.google.android.exoplayer2.ExoPlaybackException: Source error, null, null)
E/flutter (25099):我还将添加m3u8文件的内容,
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:12
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="http://192.168.1.2/key/video.key",IV=0x00000000000000000000000000000000
#EXTINF:10.666667,
playlist0.ts
#EXTINF:11.666667,
playlist1.ts
#EXT-X-ENDLIST我看到了TS文件的问题,因为错误消息显示了TsExtractor.java文件中的错误。在这里,我还试图看到一个带有curl的TS文件的HTTP响应头,
C:\Users\mdils>curl -D - http://localhost/key/playlist0.ts
HTTP/1.1 200 OK
Date: Fri, 23 Apr 2021 16:01:24 GMT
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1g PHP/7.4.11
Last-Modified: Sun, 28 Feb 2021 15:29:09 GMT
ETag: "239f80-5bc6729a3ba75"
Accept-Ranges: bytes
Content-Length: 2334592
Access-Control-Allow-Origin: *任何关于这方面的帮助都很感激。
更新
示例播放列表- https://drive.google.com/drive/folders/1Q6MJNy5HT-wlMqAUmpFBvmHaCumW73Xz?usp=sharing
用于编码的FFMPEG命令
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -hls_list_size 0 -hls_time 10 -hls_key_info_file key_info.txt playback.m3u8更新- 2021-04-25
下面是一个工作的m3u8文件,(从ExoPlayer演示应用程序复制)
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:9.97667,
fileSequence0.ts
#EXTINF:9.97667,
fileSequence1.ts
#EXTINF:9.97667,
... 将此m3u8文件与上面的文件进行比较,唯一的区别是错误的文件有一个aes-128位加密播放列表。
然后,当我检查源代码时,我在ExoPlayer源代码上找到了这个方法,
/**
* Returns the position of the end of the first TS packet (exclusive) in the packet buffer.
*
* <p>This may be a position beyond the buffer limit if the packet has not been read fully into
* the buffer, or if no packet could be found within the buffer.
*/
private int findEndOfFirstTsPacketInBuffer() throws ParserException {
int searchStart = tsPacketBuffer.getPosition();
int limit = tsPacketBuffer.limit();
int syncBytePosition =
TsUtil.findSyncBytePosition(tsPacketBuffer.getData(), searchStart, limit);
// Discard all bytes before the sync byte.
// If sync byte is not found, this means discard the whole buffer.
tsPacketBuffer.setPosition(syncBytePosition);
int endOfPacket = syncBytePosition + TS_PACKET_SIZE;
if (endOfPacket > limit) {
bytesSinceLastSync += syncBytePosition - searchStart;
if (mode == MODE_HLS && bytesSinceLastSync > TS_PACKET_SIZE * 2) {
throw new ParserException("Cannot find sync byte. Most likely not a Transport Stream.");
}
} else {
// We have found a packet within the buffer.
bytesSinceLastSync = 0;
}
return endOfPacket;
} 根据上述函数的注释,当找不到同步字节时,会抛出上述错误消息。所以,我唯一可以假设的是,玩家可能没有用提供的密钥解密第一个TS文件?(关键是正确的,因为这在HLS网络播放器上工作)
发布于 2021-04-26 14:10:31
密钥文件无效,解密TS段时会收到垃圾。关于FFmpeg的hls_key_info_file文档说:
密钥文件被读取为一个由16位字节组成的二进制格式的单个打包数组。
您的密钥文件有32个字节。如果您获取当前密钥文件的前16个字节,并以二进制格式输出它们,它将正确解密。示例:
xxd -p -l 16 video.key | xxd -r -p - video_bin.key
在播放列表中使用video_bin.key。当然,首先生成一个有效的密钥会更好。
https://stackoverflow.com/questions/67233579
复制相似问题