• PHP实现m3u8并发下载


    直接上代码

    <?php
    //php下载m3u8文件
    $url = $argv['1'];
    
    if(!file_exists('./tmp/')) {
    	if(!mkdir('./tmp/')) {
    		die('请手动在当前目录创建tmp目录');
    	}
    }
    
    $indexPage = file_get_contents($url);
    preg_match_all('/.*.ts/', $indexPage, $matches);
    if(empty($matches)) {
    	die('m3u8 文件格式错误');
    }
    
    go(function() use($matches) {
    	$chan = new chan(100); //最大并发数
    	foreach($matches['0'] as $key => $value) {
    		if(file_exists('./tmp/'.$key.'.ts')) {
    			continue;
    		}
    		$chan->push('xx');
    		go(function() use($key, $value, $chan) { 
    			echo "
    Add task:".$key;
    			while(1) {
    				$rs = co_curl($value);
    				if(strlen($rs) > 0) {
    					file_put_contents('./tmp/'.$key.'.ts', $rs);
    					break;
    				}
    			}
    			echo "
    Task ok:".$key;
    			$chan->pop();
    		});
    	}
    	//确保所有下载已经完成
    	for($i = 0; $i < 100; $i++) {
    		$chan->push('over');
    	}
    	//合并文件
    	foreach ($matches['0'] as $key => $value) {
    		file_put_contents('out.mp4', file_get_contents('./tmp/'.$key.'.ts'), FILE_APPEND);
    		unlink('./tmp/'.$key.'.ts');
    	}
    	echo "
     下载完成,转换成功 (out.mp4)";
    });
    
    
    
    
    function co_curl($url, $cookies = '', $data = array(), $userHeaders = array(), $retJson = 0)
    {
        while(1) {
            $urlInfo  = parse_url($url);
            $domain   = $urlInfo['host'];
            if($urlInfo['scheme'] == 'https') {
            	$port = 443;
            	$ssl = true;
            } else {
            	$port = isset($urlInfo['port']) ? $urlInfo['port'] : 80;
            	$ssl = false;
            }
            $filename = $urlInfo['path'];
            $filename .= isset($urlInfo['query']) ? '?' . $urlInfo['query'] : '';
    
            $cli     = new SwooleCoroutineHttpClient($domain, $port, $ssl);
            $headers = [
                'Host'            => $domain,
                "User-Agent"      => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36',
                'Accept'          => 'text/html,application/xhtml+xml,application/xml',
                'Accept-Encoding' => 'gzip',
            ];
            if ($userHeaders) {
                $headers = array_merge($headers, $userHeaders);
                $headers = $userHeaders;
            }
            if ($cookies) {
                $headers['Cookie'] = $cookies;
            }
            $cli->setHeaders($headers);
            $cli->set(['timeout' => 60]);
            if ($data) {
                if($data == 'post') {
                    $data = '';
                }
                $cli->post($filename, $data);
            } else {
                $cli->get($filename);
            }
    
            $body = $cli->body;
            $cli->close();
            
            if($cli->statusCode < 1 || ($retJson  && empty(json_decode($body, true)))) {
                // echo "
     status code:" . $cli->statusCode;
                // echo "
     body: ".$body;
                // echo "
     retry...";
            } else {
                return $body;
            }
        }
    }
    
    

    使用方法

    php index.php https://doubanzyv1.tyswmp.com/2018/07/30/LSn7hSBfY0LxpKX2/playlist.m3u8
    

    输出文件路径

    当前目录的out.mp4

  • 相关阅读:
    内存泄漏检测工具VLD在VS2010中的使用举例
    boost::threadpool 调用类成员变量并传入参数 的方法
    boost之ThreadPool
    DllMain 用法
    分布式锁的几种实现方式
    利用cbmakegen导出Code::blocks的Makefile
    搜集C++实现的线程池
    微软开源rDSN分布式系统开发框架
    腾讯互娱开源分布式开发框架Pebble
    SpringBoot指定额外需要扫描的包
  • 原文地址:https://www.cnblogs.com/dormscript/p/15088259.html
Copyright © 2020-2023  润新知