当前位置:   article > 正文

php+aira2+ffmpeg下载m3u8文件并保存成mp4_ffmpeg下载m3u8太慢

ffmpeg下载m3u8太慢

因为在线看视频时有的会比较卡顿,刚好也有闲置测试用的树莓派搭建的小服务器,本着不浪费的精神,就想着是不是能把视频下到本地,这样就不用担心卡顿了,刚好前面也记录过ffmpeg下载合并视频,以及aria2下载的,于是就有了一个不知道是不是高效安全的方式,记录下。

首先试过使用ffmpeg来直接通过外网的m3u8进行同时下载与合并生成mp4,但是发现速度很慢,只有1~3百K左右,盲猜是在一个个下ts文件,而且不知道什么原因,当到一定程度的时候,会有一定几率出现ffmpeg卡住的问题。

然后试过使用php的file_get_contents和file_put_contents来下载保存,但是一样速度超级慢,只怪Sham不会并发。

然后试了通过aria2下载,发现速度不错,家里300m宽带能到3~7MB/s浮动多。

于是就有了思路:

首先通过php来获取m3u8文件里的ts地址列表,然后生成本地用的m3u8文件,以及部分有加密用的.key文件。

然后就通过aria2c来批量下载ts地址文件中的地址。

最后就是通过ffmpeg来通过本地m3u8,获取本地的ts文件并合并生成mp4,速度明显提升

下面是Sham写的,记录备忘下

执行方法是通过网页访问这个php页,加上参数?name=xxx&m3u8=http://xxx.com/m3u8

  1. <?php
  2. if(isset($_GET['m3u8'])){
  3. //获取url
  4. $url = $_GET['m3u8'];
  5. //获取网址域名
  6. $urlarr = explode('/',$url);
  7. $domain = $urlarr[0].'//'.$urlarr[2].'/';
  8. //先判断传入的m3u8里面有没有直接包含ts地址,还是套着一个m3u8文件
  9. $url = Check_m3u8($url);
  10. //定义m3u8名字,用于区分不同的m3u8,用自定义则获取,没有则通过网址里的信息来
  11. $m3u8_name = $_GET['name']!=null && $_GET['name']!='' ? $_GET['name'] : $urlarr[3]."_".$urlarr[4];
  12. //判断、新建tslist文件夹,用于存储
  13. if(!file_exists('tslist/')){
  14. mkdir('tslist/',0777);
  15. }
  16. //通过名称建立不同文件夹
  17. $dir = 'tslist/'.$m3u8_name.'/';
  18. $ts_dir = $dir.'ts/';
  19. if(!file_exists($dir)){
  20. mkdir($dir,0777);
  21. }
  22. if(!file_exists($ts_dir)){
  23. mkdir($ts_dir,0777);
  24. }
  25. //获取m3u8文件里面的信息,并生成数组
  26. $content = explode(chr(10),file_get_contents($url));
  27. $i = 1;
  28. //这个是用来单独存储ts文件真实网址的
  29. $ts_url ='';
  30. //这个是用来新建本地m3u8文件,保证路径与下载保存的ts文件路径一致
  31. $m3u8_content = '';
  32. //通过循环来获取m3u8文件里每一行的信息
  33. foreach ($content as $v){
  34. //获取Key,并保存到本地
  35. if(strstr($v,'.key')){
  36. $get_key = explode('"',$v);
  37. $key_url = $get_key[1];
  38. //如不带域名,则添加,带了就保留
  39. $key_urls = strstr($key_url,'http') ? $key_url : $domain.$key_url;
  40. file_put_contents($dir.$m3u8_name.'_key.key',file_get_contents($key_urls));
  41. //用于本地m3u8文件,key路径与m3u8文件在同一个文件夹
  42. $m3u8_content .= $get_key[0].'"'.$m3u8_name.'_key.key"'.chr(10);
  43. }
  44. //获取正式ts文件网址
  45. elseif(strstr($v,'.ts')){
  46. //如不带域名,则添加,带了就保留
  47. $ts_urls = strstr($v,'http') ? $v : $domain.$v;
  48. $ts_url .= $ts_urls.chr(10);
  49. //获取ts文件名
  50. $ts_name = explode('/',$v);
  51. $m3u8_content .= 'ts/'.end($ts_name).chr(10);
  52. }
  53. else{
  54. $m3u8_content .= $v.chr(10);
  55. }
  56. }
  57. file_put_contents($dir.$m3u8_name.'.m3u8',$m3u8_content);
  58. file_put_contents($dir.$m3u8_name.'_ts_list.txt',$ts_url);
  59. //通过执行aria2里下载
  60. $res = shell_exec('aria2c --dir='.dirname(__FILE__).'/'.$ts_dir.' -i '.$dir.$m3u8_name.'_ts_list.txt');
  61. if($res){
  62. shell_exec('ffmpeg -allowed_extensions ALL -i '.dirname(__FILE__).'/'.$dir.$m3u8_name.'.m3u8 -c copy '.dirname(__FILE__).'/'.$dir.$m3u8_name.'.mp4');
  63. }
  64. }else{
  65. echo "请传入m3u8地址,以?m3u8=http://xxxx.com/xxx.m3u8的方式";
  66. }
  67. //判断m3u8里面有没有再包含m3u8文件
  68. function Check_m3u8($url){
  69. global $domain;
  70. $m3u8_content = file_get_contents($url);
  71. if(strstr($m3u8_content,'.m3u8')){
  72. $m3u8_contents = explode(chr(10),$m3u8_content);
  73. foreach($m3u8_contents as $m3u8){
  74. if(strstr($m3u8,'.m3u8')){
  75. $url = strstr($m3u8,'http') ? $m3u8 : $domain.$m3u8;
  76. break;
  77. }
  78. }
  79. Check_m3u8($url);
  80. }
  81. return $url;
  82. }

这个方法的缺点就是需要将PHP的最大脚本运行时间调大,不然会报502错误,还有就是需要开放shell_exec函数,不知道对安全性会不会有影响。
当然有个好处就是感觉挺快,对只会点php的人来说是个不错的方法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/246162
推荐阅读
  

闽ICP备14008679号