http://ffmpeg.org/ffmpeg-all.html#hls-3
21.13 hls
方式一: hls_key_info_file key_info_file
加密
$ catdemo.sh
#!/bin/sh
BASE_URL=${1:-'.'}
opensslrand 16> file.key
echo$BASE_URL/file.key > file.keyinfo
echofile.key >> file.keyinfo
echo$(openssl rand -hex 16)>> file.keyinfo
exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
./bin/ffmpeg -flavfi -re-itestsrc -c:v h264 -hls_flagsdelete_segments \
-hls_key_info_filefile.keyinfo out.m3u8
$
解密
$catdecrypt.sh
strkey=$(hexdump -v -e '16/1 "%02x"' file.key)
#file.keyinfo 第三行尾 aes-128-cbc 的iv
iv=$(awk 'NR==3' file.keyinfo )
opensslaes-128-cbc -d-inout42.ts -outout42_decrypto.ts -nosalt-iv$iv-K$strkey
$
#解密的out42_decrypto.ts 可以播放
方式二
-hls_enc enc
Enable (1) or disable (0) the AES128 encryption. When enabled every segment generated is encrypted and the encryption key is saved as playlist name.key.
-hls_enc_key key
Hex-coded 16byte key to encrypt the segments, by default it is randomly generated.
-hls_enc_key_url keyurl
If set, keyurl is prepended instead of baseurl to the key filename in the playlist.
Fmpeg-n4.0.2/libavformat/hlsenc.c
{"hls_enc_key_url", "url to access the key to decrypt the segments",-hls_enc_iv iv
Hex-coded 16byte initialization vector for every segment instead of the autogenerated ones.
Fmpeg-n4.0.2/libavformat/hlsenc.c
{"hls_enc_key_url", "url to access the key to decrypt the segments",
#1.没有指定 -hls_enc_key_url 时,在当前目录下产生一个 out.m3u8.key 的文件为 密钥
exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
./bin/ffmpeg -flavfi -re-itestsrc -c:v h264 -hls_flagsdelete_segments \
-hls_enc1-hls_enc_key"123456890abcdef"-hls_enc_iv"1122334455aabbcc"out.m3u8
$catout.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:9
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="out.m3u8.key",IV=0x31313232333334343535616162626363
#EXTINF:9.360000,
out0.ts
#EXT-X-ENDLIST
#解密,密钥 out.m3u8.key
strkey=$(hexdump -v -e '16/1 "%02x"' out.m3u8.key)
#iv=$(awk 'NR==3' file.keyinfo )
iv=31313232333334343535616162626363
opensslaes-128-cbc -d-inout27.ts -outout27_decrypto.ts -nosalt-iv$iv-K$strkey
#2. 指定了hls_enc_key_url ,ffmpeg 通过 http 1.1协议 发送16字节的密钥 (Transfer-Encoding: chunked)
$exportLD_LIBRARY_PATH=./lib:$LD_LIBRARY_PATH
$ ./bin/ffmpeg -flavfi -re-itestsrc -c:v h264 -hls_flagsdelete_segments -hls_enc1-hls_enc_key"123456890abcdef"-hls_enc_key_url"http://127.0.0.1:8000"-hls_enc_iv"1122334455aabbcc"out.m3u8
[fanshuang@zhifudev01v python]$ pythonpost.py
('127.0.0.1', 49950)
<BaseHTTPServer.HTTPServer instance at 0x7fa14385b9e0>
POST
/
HTTP/1.1
Transfer-Encoding: chunked
User-Agent: Lavf/58.12.100
Accept: */*
Connection: close
Host: 127.0.0.1:8000
Icy-MetaData: 1
<socket._fileobject object at 0x7fa139de2bd0>
begin http1.1 chunked ..........
chunk-size hex: 0X10
, need recv 16bytes
chunk-data:123456890abcdef
('str_chunk_size_hex:[\r\n] , ValueError:', ValueError("invalid literal for int() with base 16: ''",))
begin http1.1 end ..........
127.0.0.1 --[11/Nov/2018 14:56:03] "POST / HTTP/1.1"200-
$$catpost.py
#coding=utf-8
from BaseHTTPServer import BaseHTTPRequestHandler
import cgi
class PostHandler(BaseHTTPRequestHandler):
def chunked_proc(self):
print 'begin http1.1 chunked .......... \n'
str_chunk_size_hex=self.rfile.readline(65537)
len =int(str_chunk_size_hex.upper(), 16)
whilelen > 0:
print "chunk-size hex: 0X"+str_chunk_size_hex +', need recv '+str(len) +' bytes \n'
print "chunk-data:"+self.rfile.readline(len)
str_chunk_size_hex=self.rfile.readline(65537)
try:
len =int(str_chunk_size_hex, 16)
except ValueError as e:
len =0
print( 'str_chunk_size_hex:['+str_chunk_size_hex +']'+' , ValueError:',e)
print 'begin http1.1 end .......... \n'
def do_POST(self):
print self.client_address
print self.server
print self.command
print self.path
print self.request_version
print self.headers
print self.rfile
ifself.headers['Transfer-Encoding'] =='chunked':
self.chunked_proc()
#self.send_header('Transfer-Encoding', 'chunked')
#self.send_header('Connection', 'keepalive')
self.send_response(200)
self.end_headers()
#print self.responses
return
def StartServer():
from BaseHTTPServer import HTTPServer
sever =HTTPServer(("",8000),PostHandler)
sever.serve_forever()
if__name__=='__main__':
StartServer()
$
$ find. -name"*.c"| xargs grephls_enc_key_url
./libavformat/hlsenc.c: {"hls_enc_key_url", "url to access the key to decrypt the segments", OFFSET(key_url), AV_OPT_TYPE_STRING, {.str =NULL}, 0, 0, E},
$
Fmpeg-n4.0.2/libavformat/hlsenc.c
{"hls_enc_key_url", "url to access the key to decrypt the segments",
urltoaccessthekeytodecryptthesegments
staticconstAVOptionoptions[] ={
//....
{"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, E},
{"hls_enc_key", "hex-coded 16 byte key to encrypt the segments", OFFSET(key), AV_OPT_TYPE_STRING, .flags=E},
{"hls_enc_key_url", "url to access the key to decrypt the segments", OFFSET(key_url), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, E},
{"hls_enc_iv", "hex-coded 16 byte initialization vector", OFFSET(iv), AV_OPT_TYPE_STRING, .flags=E},
{ NULL},
};
staticintdo_encrypt(AVFormatContext*s, VariantStream*vs){
//.....
av_strlcpy(hls->key_basename, s->url, len);
av_strlcat(hls->key_basename, ".key", len);
if(hls->key_url) {
av_strlcpy(hls->key_file, hls->key_url, sizeof(hls->key_file));
av_strlcpy(hls->key_uri, hls->key_url, sizeof(hls->key_uri));
} else{
av_strlcpy(hls->key_file, hls->key_basename, sizeof(hls->key_file));
av_strlcpy(hls->key_uri, hls->key_basename, sizeof(hls->key_uri));
}
//.....
}
文章转载自科学杂谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。





