<?php namespace Api\Video\Handle;
use Dever;
use Dever\Helper\Cmd;
class Clip
{
    private $cmd;
    # ffmpeg [global options] [input file options] -i input_file [output file options] output_file
    public function info($file, $print = false)
    {
        $info = $this->act($file, false, false, $print);
        $info = implode("\r\n", $info);
        $data = array();
         if (preg_match("/Duration: (.*?), start: (.*?), bitrate: (\d*) kb\/s/", $info, $match)) {
             $data['duration'] = $match[1]; //播放时间
             $arr_duration = explode(':', $match[1]);
             $data['seconds'] = $arr_duration[0] * 3600 + $arr_duration[1] * 60 + $arr_duration[2]; //转换播放时间为秒数
             $data['start'] = $match[2]; //开始时间
             $data['bitrate'] = $match[3]; //码率(kb)
         }
         if (preg_match("/Video: (.*?), (.*?), (.*?), (.*?)[,\s]/", $info, $match)) {
             $data['vcodec'] = $match[1]; //视频编码格式
             $data['vformat'] = $match[2]; //视频格式
             if (strstr($match[3], 'x')) {
                $data['resolution'] = $match[3]; //视频分辨率
            } elseif (strstr($match[4], 'x')) {
                $data['resolution'] = $match[4]; //视频分辨率
             }
             $arr_resolution = explode('x', $data['resolution']);
             $data['width'] = $arr_resolution[0];
             $data['height'] = $arr_resolution[1];
         }
         if (preg_match("/Audio: (\w*), (\d*) Hz/", $info, $match)) {
             $data['acodec'] = $match[1]; //音频编码
             $data['asamplerate'] = $match[2]; //音频采样频率
         }
         if (isset($data['seconds']) && isset($data['start'])) {
             $data['play_time'] = $data['seconds'] + $data['start']; //实际播放时间
         }
         $data['size'] = filesize($file); //文件大小
         return $data;
    }
    public function act($input, $output, $option = array(), $print = false)
    {
        $this->cmd = array('/usr/local/ffmpeg4/bin/ffmpeg');
        //$this->cmd = array('ffmpeg');
        $this->cmd[] = $this->input($input);
        if ($option) {
            foreach ($option as $k => $v) {
                if (!is_array($v) || ($k == 'video' || $k == 'audio' || $k == 'filter_complex')) {
                    $v = array($v);
                }
                $this->cmd[] = call_user_func_array(array($this, $k), $v);
            }
        }
        if ($output) {
            $this->cmd[] = $this->output($output);
            $shell = $output . '.sh';
        } else {
            $shell = $input . '.sh';
        }
        $cmd = implode(' ', $this->cmd);
        if ($print) {
            print_r($cmd);die;
        }
        file_put_contents($shell, 'source /etc/profile && ' . $cmd . ' 2>&1');
        $cmd = 'chmod +x ' . $shell . ' && ' . $shell . ' && rm -rf ' . $shell;
        $result = Cmd::shell($cmd, false);
        if ($result[1]) {
            if ($output) {
                return is_array($output) ? $output['file'] : $output;
            } else {
                return $result[1];
            }
        }
        return false;
    }

    # 获取视频
    public function input($video)
    {
        if (is_array($video)) {
            return $this->option($video['option'] ?? array(), ' -i ' . $video['file']);
        }
        return '-i ' . $video;
    }

    # 输出视频
    public function output(&$video)
    {
        if (is_array($video)) {
            $result = $this->option($video['option'] ?? array(), ' ' . $video['file']);
            $video = $video['file'];
            return $result;
        }
        return '-y -b:v 10000k ' . $video;
    }

    # 按照时间截取
    public function time($max, $start = 0)
    {
        return '-ss ' . gmdate('H:i:s', $start) . ' -t ' . gmdate('H:i:s', $max);
    }

    # video过滤器
    public function video($video = array())
    {
        if ($video) {
            $cmd = array();
            foreach ($video as $k => $v) {
                $cmd[] = $this->filter('video', $k, $v);
            }
            return '-vf "'.implode(',', $cmd).'"';
        }
        return '';
    }

    # audio过滤器
    public function audio($audio = array())
    {
        if ($audio) {
            $cmd = array();
            foreach ($audio as $k => $v) {
                $cmd[] = $this->filter('audio', $k, $v);
            }
            return '-af "'.implode(',', $cmd).'"';
        }
        return '';
    }

    # 复杂过滤器
    public function filter_complex($param)
    {
        $cmd = array();
        foreach ($param as $k => $v) {
            $cmd[] = $v;
        }
        return '-filter_complex "'.implode(';', $cmd).'"';
    }

    # 过滤器 -简单过滤器
    public function filter($type, $method, $param)
    {
        $class = Dever::load('handle/filter/' . $type, 'api', 'video')->class;
        if (method_exists($class, $method)) {
            if (!is_array($param)) {
                $param = array($param);
            }
            return call_user_func_array(array($class, $method), $param);
        } else {
            if (is_array($param)) {
                $tmp = array();
                foreach ($param as $k => $v) {
                    if ($v) {
                        $v = '=' . $v;
                    }
                    $tmp[] = $k . $v;
                }
                $param = implode(':', $tmp);
            }
            if ($param) {
                $param = '=' . $param;
            }
            return $method . $param;
        }
    }

    # 获取选项
    private function option($option, $suffix = '')
    {
        $tmp = array();
        if ($option) {
            foreach ($option as $k => $v) {
                if ($v) {
                    $v = ' ' . $v;
                }
                if (is_string($k) && $k) {
                    $tmp[] = '-' . $this->alias($k) . $v;
                } else {
                    $tmp[] = $v;
                }
            }
        }
        return implode(' ', $tmp) . $suffix;
    }

    # 设置别名
    private function alias($k)
    {
        if ($k == 'audio') {
            return 'b:a';
        }
        if ($k == 'video') {
            return 'b:v';
        }
        return $k;
    }
}