php自动获取m3u8,php – 如何通过在浏览器中粘贴URL来创建动态m3u8?

我想在调用PHP脚本时创建动态m3u8.我不想将结果m3u8保存在服务器上,而是想将其推送到浏览器以便可下载.有谁能告诉我如何才能完成这项任务?

要调用的PHP脚本示例:

http://www.asite.com/makeM3u8.php?videoId=1234

可下载的动态m3u8结构:

#EXTM3U

#EXT-X-VERSION:3

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=900000

http://someserver/channelNameBandwith900000.m3u8?session=3495732948523984eriuwehiurweirew

解决方法:

在进入脚本之前,您必须先决定一些事情:

1.- .ts和.aac文件存储在哪里,它们的保护方案是什么?PHP是否能够创建能够访问它们的URL?

2.-存储原始m3u8信息的位置(每个段的目标持续时间,extinf和名称).在这种情况下,数据库比解析现有文件更快.

3.-如果处理多比特率,你需要一个脚本,它也生成指向所有其他的主m3u8.

话虽这么说,这是我提出的解决方案,并且已经使用了一段时间没有问题.但有两点,我使用AWS S3进行存储,并使用ffmpeg转换现有的视频文件.这是一个相当漫长的过程 – 对你想要的东西来说可能有些过分 – 但它确实有效.

第1部分 – 编码文件系统接收MP4视频并将其转换为必需的格式.

function ffConvert($origin,$basedir,$res) {

switch($res) {

// SET THE VARIABLES

case "240p": $size = "426x240"; $vbit = "360k"; $level = "3.0"; $abit = "80k"; break;

case "480p": $size = "854x480"; $vbit = "784k"; $level = "3.1"; $abit = "128k"; break;

case "720p": $size = "1280x720"; $vbit = "1648k"; $level = "3.1"; $abit = "192k"; break;

}

// CONVERT THE FILES

exec('/usr/local/bin/ffmpeg -y -async 1 -vsync -1 -analyzeduration 999999999 -i "'.$origin.'" -force_key_frames "expr:gte(t,n_forced*10)" -pix_fmt yuv420p -s '.$size.' -r:v 30 -b:v '.$vbit.' -c:v libx264 -profile:v baseline -level '.$level.' -c:a libfaac -ac 2 -ar 48000 -b:a '.$abit.' -g 90 '.$base.$res.'.mp4');

// VERIFY AND RETURN

if(file_exists($basedir.$res.'.mp4')) {

return TRUE;

} else {

return FALSE;

}

}

第2部分 – 分割文件系统采用转换后的MP4并对其进行分段.

function ffSegment($basedir,$res) {

// CREATE THE SEGMENTS

mkdir($basedir.$res, 0775);

exec('/usr/local/bin/ffmpeg -y -analyzeduration 999999999 -i "'.$basedir.$res.'.mp4" -codec copy -map 0 -f segment -segment_list "'.$basedir.$res.'/stream.m3u8" -segment_time 10 -segment_list_type m3u8 -bsf:v h264_mp4toannexb "'.$basedir.$res.'/segment%05d.ts"');

if(file_exists($basedir.$res.'/stream.m3u8')) {

return TRUE;

} else {

return FALSE;

}

}

第3部分 – 存储数据系统解析生成的m3u8并将相关信息存储在数据库中.

表:

CREATE TABLE IF NOT EXISTS `data_contenido_archivos` (

`id` bigint(20) unsigned NOT NULL,

`240p` mediumtext NOT NULL,

`480p` mediumtext NOT NULL,

`720p` mediumtext NOT NULL,

`aac` mediumtext NOT NULL,

UNIQUE KEY `id` (`id`)

) ENGINE=TokuDB DEFAULT CHARSET=utf8;

解析功能:

function parseHLS($file) {

$return = array();

$i = 0;

$handle = fopen($file, "r");

if($handle) {

while(($line = fgets($handle)) !== FALSE) {

if(strpos($line,"#EXTINF") !== FALSE) {

$return['data'][$i]['inf'] = str_replace(array("#EXTINF:",",","\r","\n"),array("","","",""),$line);

}

if(strpos($line,".ts") !== FALSE) {

$return['data'][$i]['ts'] = str_replace(array(".ts","segment","\r","\n"),array("","","",""),$line);

$i++;

}

if(strpos($line,"TARGETDURATION") !== FALSE) {

$return['duration'] = str_replace(array("#EXT-X-TARGETDURATION:","\r","\n"),array("","","",""),$line);

}

}

fclose($handle);

} else {

$retorno = FALSE;

}

return $return;

}

每个文件的结果都存储在每个视频大小的相对列中,作为json编码的字符串,请注意我存储了可能的最小信息,以便最大限度地缩短读取时间并使dB尽可能小.在此步骤中,速度并不重要,因为这是在提供文件之前完成的.

第4部分 – 提供文件系统读取数据库并为每个大小提供正确的文件.

为此,我有一个m3u8.domain.com设置,它将所有* .m3u8文件发送到PHP解释器,所以我不打扰重命名,这只提供以下文件:

> crossdomain.xml

> 240p.m3u8:240p分辨率的脚本

> 480p.m3u8:480p分辨率的脚本

> 720p.m3u8:720p分辨率的脚本

> aac.m3u8:仅用于音频的脚本

> master.m3u8:主m3u8的脚本

每个都是它自己的文件,因为如果不同的带宽m3u8都具有相同的名称,一些播放器会出现问题.

master.m3u8这样做:

if($sesion !== FALSE) {

$hls = sql("SELECT A.240p,A.480p,A.720p,A.aac,B.duracion FROM data_contenido_archivos A, data_contenido B WHERE A.id = '".limpia($_GET['i'])."' AND B.id = '".limpia($_GET['i'])."'");

if($hls['status'] == "OK") {

$return = "#EXTM3U\n";

if($hls['data'][0]['240p'] != "{}") {

$return .= "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=440000, RESOLUTION=426x240\n";

$return .= $domains['m3u8']."/240p.m3u8?i=".$id."&s=".$sesion."\n";

}

if($hls['data'][0]['480p'] != "{}") {

$return .= "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=912000, RESOLUTION=854x480\n";

$return .= $domains['m3u8']."/480p.m3u8?i=".$id."&s=".$sesion."\n";

}

if($hls['data'][0]['720p'] != "{}") {

$return .= "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1840000, RESOLUTION=1280x720\n";

$return .= $domains['m3u8']."/720p.m3u8?i=".$id."&s=".$sesion."\n";

}

if($hls['data'][0]['aac'] != "{}") {

$retorno .= "#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=64000\n";

$retorno .= $domains['m3u8']."/aac.m3u8?i=".$id."&s=".$sesion."\n";

}

}

}

header("Content-type: application/x-mpegURL");

echo $return;

它,在数据库中查询所有不同的分辨率,并为每个分辨率回显正确的URL.如果它不存在(在我的方案中设置为{}),则不会回显.

然后每个res.m3u8执行以下操作(调用时):

if($sesion) {

$hls = sql("SELECT A.240p,B.duracion FROM data_contenido_archivos A, data_contenido B WHERE A.id = '".limpia($_GET['i'])."' AND B.id = '".limpia($_GET['i'])."'");

if($hls['estado'] == "OK") {

$data = json_decode($hls['data'][0]['240p'],TRUE);

// INICIAMOS EL ARCHIVO

$retorno = "#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-MEDIA-SEQUENCE:0\n#EXT-X-ALLOW-CACHE:YES\n#EXT-X-TARGETDURATION:".$data['duration']."\n";

// CALCULAMOS EL VENCIMIENTO (1.5x DURACION DEL VIDEO)

$vence = "+".floor($hls['data'][0]['duracion'] / 60)." minutes";

foreach($data['data'] as $k=>$v) {

$retorno .= "#EXTINF:".$v['inf'].",\n";

$retorno .= S3URL("",$_GET['i']."/240p/segment".$v['ts'].".ts",$vence)."\n";

}

$retorno .= "#EXT-X-ENDLIST\n";

}

}

header("Content-type: application/x-mpegURL");

echo $retorno;

这里发生了一些事情,让我解释一下:

a.-首先脚本检查一个有效的会话,如果一个不存在,它会为一个小的10秒视频提供一个m3u8,说“你没有权限查看这个”.

b.-如果会话签出,它会查询数据库并获取所有必需的JSON.它还查询另一个表,我存储文件的持续时间,以便填充TARGETDURATION字符串,并计算要生成的安全S3 URL的生命周期.我将URL的生命周期设置为视频长度的1.5倍,它对我有用,您的体验可能会有所不同.

c.-然后它从数据库中遍历每个组,回显EXTINF并为每个组生成一个安全的URL.

标签:php,m3u8

来源: https://codeday.me/bug/20190725/1529962.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值