吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13940|回复: 25
收起左侧

[其他转载] php无人值守录制抖音直播

   关闭 [复制链接]
Jonasen 发表于 2021-7-21 12:34

为了家中老人,老人有的时候不在家,关注的主播直播内容就容易错过,用python是可以录制,但是家中老人还不会弄电脑,就衍生了这个项目-_-!

原理

  1. 安装ffmpeg
  2. php解析抖音直播地址
  3. php调用ffmpeg将转换过来的直播地址进行录制
  4. 添加定时任务,定时调用脚本

安装ffmpeg

我的环境是centos7.x,先更新下yum,采用yum的方式进行安装ffmpeg,先更新下当前yum

yum -y update

安装Nux Dextop Yum 源(慎重操作)

sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

安装FFmpeg 和 FFmpeg开发包

sudo yum install ffmpeg ffmpeg-devel -y

测试ffmpeg是否成功安装

ffmpeg

*这里补充下,我的环境是宝塔环境,宝塔之前的一键包安装ffmpeg已经失效了,问题很多,在这里不建议大家采用宝塔的一键包,我现在的安装方案是采用宝塔论坛 CentOS7宝塔面板安装ffmpeg视频切片模块  yaojiu的安装方式。

解析抖音直播地址

这里的抖音直播源解析是通过我前一段时间写的php抖音直播源抓取进行的解析,原理就是所有的信息都在 window.__INIT_PROPS__这个部分当中,而这部分内容是json结构的,所以我们只要将这部分代码转为能够读取的json然后进行调用就可以,需要的小伙伴自行观看。
这里放上thinkphp抓取抖音直播源的源码:

<?php
/****抖音直播解析接口*******/
namespace app\controller;
use app\BaseController;
use think\facade\Request;

class Douyin extends BaseController
{
    public function index(){
        $url=Request::param('url');
        $html=$this->get_douyin($url);
        preg_match_all('/window.__INIT_PROPS__ =(.*)<\/script><\/head>/', $html, $jsmatch);
        if(!empty($jsmatch[1][0])){
            $content=json_decode($jsmatch[1][0],1);
            if(!empty($content['/webcast/reflow/:id']['room']['stream_url']['hls_pull_url'])){
                $data=array(
                    'code'=>200,
                    'success'=>true,
                    'data'=>array(
                        'url'=>$content['/webcast/reflow/:id']['room']['stream_url']['hls_pull_url'],
                        'title'=>$content['/webcast/reflow/:id']['room']['title'],
                        'id'=>$content['/webcast/reflow/:id']['room']['id'],
                        'status'=>$content['/webcast/reflow/:id']['room']['status']
                    )
                );
                echo json_encode($data);
            }else{
                $data=array(
                    'code'=>400,
                    'success'=>false,
                    'msg'=>'数据接口请求失败'
                );
                echo json_encode($data);
            }
        }
    }
    private  get_douyin($url,$post='',$cookie='', $returnCookie=0,$header=array(),$referer=''){
        $curl = curl_init();
        if(!empty($header)){
            curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
            curl_setopt($curl, CURLOPT_HEADER, 0);//返回response头部信息
        }
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 跳过证书验证(https)的网站无法跳过,会报错
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书验证
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Linux; U; Android 8.1.0; en-US; Nexus 6P Build/OPM7.181205.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/12.11.1.1197 Mobile Safari/537.36');
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_REFERER, $referer);
        if($post) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
        }
        if($cookie) {
            curl_setopt($curl, CURLOPT_COOKIE, $cookie);
        }
        curl_setopt($curl, CURLOPT_HEADER, $returnCookie);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($curl);
        if (curl_errno($curl)) {
            return curl_error($curl);
        }
        curl_close($curl);
        if($returnCookie){
            list($header, $body) = explode("\r\n\r\n", $data, 2);
            preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
            $info['cookie']  = substr($matches[1][0], 1);
            $info['content'] = $body;
            return $info;
        }else{
            return $data;
        }

}
}

传递回来的参数为:


{"code":200,"success":true,"data":{"url":"http:\/\/pull-hls-l6.douyincdn.com\/stage\/stream-685625243370782751_or4\/index.m3u8","title":"jonasen\u6b63\u5728\u76f4\u64ad","id":6986527143291637000,"status":2}}

php调用ffmpeg进行录制

php如果直接调用ffmpeg是不行的,我们需要执行proc_open,proc_get_status,proc_close命令,所以要将php.ini中对应的命令启用。

我这里做了个自动判断直播状态,传递回来的参数中如果status不等于2的情况下,代表当前录播已经停止,所以执行一次停止直播的命令,虽然ffmpeg在抖音关播以后会自动停止(亲测),但是保险期间还是做了一个容错。

以下是我用thinkphp5测试过后的代码:

<?php
/****抖音直播录制接口*******/
namespace app\controller;
use app\BaseController;
use think\facade\Request;
class Live extends BaseController
{
    public function index(){
        $url=Request::param('url');
        $status=Request::param('status');//停止录播传个任意参数
        $apiUrl="http://xx/Douyin?url=".$url;//获取抖音直播的接口,见本博客
        $returnData=file_get_contents($apiUrl);
        $data=json_decode($returnData,true);
        if($data['code']==200){
            if($data['data']['status']==2){
                if(!empty($status)){
                    if(!file_exists($data['data']['id'].".txt")){
                        echo "当前直播不存在";
                        die();
                    }
                    $pid=file_get_contents($data['data']['id'].".txt");
                    proc_close(proc_open('kill -9 '.$pid, array(), $pipes));//杀死进程
                    unlink($data['data']['id'].".txt");
                    echo "已停止录播";
                    exit();
                }
                //判断当前直播是否正在录屏中
                if(file_exists($data['data']['id'].".txt")){
                    echo "当前直播正在进行中";
                    die();
                }
                //直播正在进行中
                $command="ffmpeg -i ".$data['data']['url']." -c copy -bsf:a aac_adtstoasc -f mp4 /www/wwwroot/当前网站路径/public/upload/".$data['data']['id'].".mp4 >/dev/null 2>&1 &";
                $process = proc_open($command, array(),$pipes); //执行录屏命令
                $var = proc_get_status($process); //获取命令进程信息
                $pid = intval($var['pid'])+1;//pid就是进程ID,$var['pid']得到的ID比实际的少1
                $pidFile = fopen($data['data']['id'].".txt", "w+");//创建当前任务信息文档
                fwrite($pidFile, $pid);
                fclose($pidFile);
                echo "正在录播";
            }else{
                $pid=file_get_contents($data['data']['id'].".txt");
                proc_close(proc_open('kill -9 '.$pid, array(), $pipes));//杀死进程
                unlink($data['data']['id'].".txt");
                echo "已停止录播";
                exit();
                //结束
                echo "直播已经结束";
            }
        }else{
            echo "未获取到直播信息";
        }
    }

}

计划任务

在宝塔中添加定时任务,访问地址为:

请输入图片描述

相关网址

开始直播:
http://xxx.cn/Live?url=https://v.douyin.com/et3Nt53/

结束直播:
http://xxx.cn/Live?url=https://v.douyin.com/et3Nt53/&status=1

免费评分

参与人数 8吾爱币 +7 热心值 +5 收起 理由
banhave + 1 我很赞同!
maoxingren + 1 + 1 谢谢@Thanks!
JUNGLE_CN + 1 + 1 我很赞同!
我是一个外星人 + 1 谢谢@Thanks!
wangyuchuandeyu + 1 + 1 我很赞同!
jackyuan666 + 1 我很赞同!
taobing + 1 + 1 我很赞同!
iverson76ers + 1 &amp;lt;font style=&amp;quot;vertical-align: inherit;&amp;quot;&amp;gt;&amp;lt;font style=

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Jonasen 发表于 2021-7-21 14:33
这里需要补充下,使用该脚本,可以同时录播多个直播。
onemores 发表于 2022-3-14 23:44
题主  有个问题期待回复  就是怎么同时录制多个直播呢,开一个ffmpeg录制CPU就已经跑满了   两个ffmpeg进程电脑基本跑不动了? 这个怎么解决呢?
piazini 发表于 2022-1-6 21:25
wzyl 发表于 2021-7-21 13:58
php果然是世界上最好的编程语言  赞一个

最好的编程语言,为啥这么说?
3300452914 发表于 2021-7-21 13:25
谢谢大佬
mafeng123 发表于 2021-7-21 13:37
厉害厉害,这个6.省一大堆事
吾爱游客  发表于 2021-7-21 13:38
谢谢大佬
shuiaohuaheng 发表于 2021-7-21 13:43
厉害厉害。。试一下效果
www805 发表于 2021-7-21 13:47
相当牛逼。
lyjsolo 发表于 2021-7-21 13:47
谢谢分享!学习了
隔壁小赖 发表于 2021-7-21 13:49

谢谢大佬分享
wzyl 发表于 2021-7-21 13:58
php果然是世界上最好的编程语言  赞一个
katitus 发表于 2021-7-21 14:05
太牛逼了!!!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 21:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表