public function submit_transcode() { //构建提交转码的参数 /* if($this->input['vod_config_id']) { $type_id = $this->input['vod_config_id']; $condition = " AND type_id=".$type_id; } else { $condition = " AND is_default=1"; } $vod_config = transcode_config($condition); */ $vod_config = transcode_config($this->input['vod_config_id']); $is_file = 0; //标识是否是文件上传 $is_url = 0; //标识是否是url提交 if ($_FILES) { $max_size = ini_get('upload_max_filesize'); if ($max_size) { if ($_FILES['videofile']['size'] > $max_size * 1024 * 1024) { $this->errorOutput('上传视频不能超过' . $max_size . 'M'); } } $is_file = 1; $this->check_has_videofile($vod_config); $this->input['filepath'] = $this->dir_info['filepath']; } elseif ($this->input['url']) { //检查url连接 $is_url = 1; $url = $this->input['url']; $basename = basename($url); $r = strpos($basename, '.'); //这里需要修改 if (!$r) { $this->errorOutput('下载链接不正确'); } //检查文件格式 $filetype = strtolower(strrchr($basename, '.')); $allowtype = explode(',', $this->settings['video_type']['allow_type']); if (!in_array($filetype, $allowtype)) { $this->errorOutput(FORBIDTYPE); } if (!$this->input['title']) { $this->input['title'] = $basename; } //构建下载目录 $dir = UPLOAD_DIR . 'url/' . hg_build_dowload_dir(); //构建目标视频目录 $v_videodir = create_video_dir(); $vod_dir_names = $v_videodir[0]; $video_dir = $v_videodir[1]; if (!hg_mkdir(TARGET_DIR . $video_dir) || !is_writeable(TARGET_DIR . $video_dir)) { $this->errorOutput(NOWRITE); } $this->dir_info['target_dir'] = $video_dir; $this->dir_info['output_filename'] = $vod_dir_names . ''; $this->dir_info['output_format'] = $vod_config['output_format']; //开始下载 $re = $this->download_from_url($url, $dir); if ($re) { $this->input['filepath'] = strrchr($re, 'url'); } else { $this->errorOutput('下载失败'); } //如果不需要转码,拷贝一份到目标视频目录(注: IS_TRANSCODE_URL只用于url提交) if (!defined('IS_TRANSCODE_URL')) { //$source = $dir.basename($url); $dest = TARGET_DIR . $video_dir . $vod_dir_names . strrchr(basename($url), '.'); $re = copy($re, $dest); if (!$re) { $this->errorOutput('复制失败'); } } } else { if (!$this->input['notcheck']) { if (!$this->input['filepath'] || !file_exists(UPLOAD_DIR . $this->input['filepath'])) { $this->errorOutput(NOTFINDFILE); } } //如果没传title就取文件名 if (!$this->input['title']) { $_path_name = basename($this->input['filepath']); $this->input['title'] = substr($_path_name, 0, strrpos($_path_name, '.')); } if ($this->settings['video_cloud'] && $this->settings['video_file_cloud'] == 1) { include CUR_CONF_PATH . 'lib/cloud/' . $this->settings['video_cloud'] . '.php'; $cloud = new $this->settings['video_cloud'](); $uparray = array('name' => $this->input['title'], 'tmp_name' => UPLOAD_DIR . $this->input['filepath'], 'size' => filesize(UPLOAD_DIR . $this->input['filepath'])); $cloud->setFiles($uparray); $cloud->setInput($this->input); $cloud->setSettings($this->settings); $ret = $cloud->upload(); $videoinfo = $cloud->getVideoInfo(); $this->input['content_id'] = $videoinfo['content_id']; $this->input['extend_data'] = $videoinfo['extend_data']; $this->input['notranscode'] = $videoinfo['notranscode']; $this->dir_info['original'] = $original; if ($ret != 'success') { $this->errorOutput($ret); } } else { $this->create_dir($vod_config); } } $video = $this->input; $v_vinfo = $this->storage_data($video, $vod_config); //如果不需要转码,则直接返回 if (!defined('IS_TRANSCODE_URL') && $is_url) { //将转码状态置为1 $sql = "UPDATE " . DB_PREFIX . "vodinfo SET status=1 WHERE id = '" . $v_vinfo['vid'] . "'"; $this->db->query($sql); $this->addItem($v_vinfo); $this->output(); } $vid = $v_vinfo['vid']; $img_info = $v_vinfo['img_info']; if ($video['audit_auto']) { $this->settings['App_mediaserver']['extends'] = $video['audit_auto']; } else { $defaultstate = $this->get_status_setting('create'); if ($defaultstate) { $defaultstate = 2; } $this->settings['App_mediaserver']['extends'] = $defaultstate; } //传到转码服务器的duration参数的单位是秒,所以此处因为接受外部的时间单位是ms if (!$this->input['notranscode']) { if ($is_file || $is_url) { $duration = ''; $start = '0'; } else { $duration = $video['duration'] ? $video['duration'] : intval($video['end'] - $video['start']) / 1000 . ''; $start = $video['start']; } $source_arr = array('source' => UPLOAD_DIR . $video['filepath'], 'start' => $start, 'duration' => $duration, 'is_water_marked' => '0'); $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $data = array("sourceFile" => array($source_arr), "id" => "{$vid}", "app_id" => APPID, "app_key" => APPKEY, "type" => "transcode_upload", "targetDir" => TARGET_DIR . $this->dir_info['target_dir'], "output_filename" => $this->dir_info['output_filename'], "config" => $vod_config, "callback" => $this->settings['App_mediaserver'], "ts_need_preprocess" => $video['ts_need_preprocess'] ? '1' : '0', "mp4_from_sobey" => $video['mp4_from_sobey'] ? '1' : '0', "force_recodec" => $video['force_recodec'] ? '1' : '0', "absolute_path" => '1'); //加马赛克(优先采用用户提供的自定义的马赛克) if ($video['mosaic']) { $mosaic = explode(',', $video['mosaic']); if (count($mosaic) == 4) { $mosaicArr = array('x' => $mosaic[0], 'y' => $mosaic[1], 'width' => $mosaic[2], 'height' => $mosaic[3]); $data['config']['mosaic'] = $mosaicArr; } } elseif ($video['mosaic_id']) { $mosaic_mode = new mosaic_mode(); $mosaic_config = $mosaic_mode->detail($video['mosaic_id']); if ($mosaic_config) { $data['config']['mosaic'] = array('x' => $mosaic_config['x'], 'y' => $mosaic_config['y'], 'width' => $mosaic_config['width'], 'height' => $mosaic_config['height']); } } //指定不用加水印 if ($video['no_water']) { $data['config']['water_mark'] = ''; } else { if ($video['water_id']) { $water_mode = new water_config_mode(); $waterInfo = $water_mode->detail($video['water_id']); if ($waterInfo) { $data['config']['water_mark'] = $waterInfo['base_path'] . $waterInfo['img_path']; if ($video['water_pos']) { $_pos = explode(',', $video['water_pos']); } else { $_pos = explode(',', WATER_POS); //如果没传位置,就用默认位置 } $data['config']['water_mark_x'] = $_pos[0]; $data['config']['water_mark_y'] = $_pos[1]; } } else { if ($data['config']['water_mark'] && $video['water_pos']) { $_pos = explode(',', $video['water_pos']); $data['config']['water_mark_x'] = $_pos[0]; $data['config']['water_mark_y'] = $_pos[1]; } } } //头信息 if ($this->settings['metadata']) { $metadata = $this->settings['metadata']; foreach ($metadata as $k => $v) { if (!$v) { unset($metadata[$k]); } else { $metadata[$k] = urlencode($v); } } $data['metadata'] = $metadata; } //记录水印与马赛克的参数,在强制转码的时候可能会用到这些参数,因为在第一次转码的时候不一定是强制转码,这样水印与马赛克不一定有 $_param = array('mosaic' => $data['config']['mosaic'], 'water' => array('water_mark' => $data['config']['water_mark'], 'water_mark_x' => $data['config']['water_mark_x'], 'water_mark_y' => $data['config']['water_mark_y']), 'metadata' => $data['metadata']); if (!is_dir(UPLOAD_DIR . 'water/')) { hg_mkdir(UPLOAD_DIR . 'water/'); } file_put_contents(UPLOAD_DIR . 'water/' . $vid . '.json', json_encode($_param)); //选取转码服务器 if ($video['server_id']) { $tran_server = select_servers_by_id($video['server_id'], $vid); } else { $tran_server = select_servers($vid); //自动选择转码服务器 } if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } $trans = new transcode($tran_server); //根据选取到转码服务器是否需要携带文件,选择各自的提交方式 if ($tran_server['need_file']) { $data['upload_file_in_callback'] = "1"; $data['sourceFile'][0]['url'] = 'http://' . ltrim(SOURCE_VIDEO_DOMIAN, 'http://') . '/' . $source_arr['source']; } $ret = $trans->addTranscodeTask($data); $return = json_decode($ret, 1); } if ($return['return'] == 'fail') { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$vid}"; $this->db->query($sql); hg_do_transcode_fail($data, $vid); //将转码失败的信息记录下来 $error_info = array('return' => 'success', 'transcode' => 'fail', 'tran_server' => $tran_server, 'id' => $vid, 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'img' => $img_info, 'ErrorCode' => '0x0025', 'ErrorText' => '提交转码失败'); echo json_encode($error_info); //上传成功,转码失败 } else { //返回数据 $video_info = array('id' => $vid, 'protocol' => 'http://', 'host' => defined("TARGET_VIDEO_DOMAIN") ? ltrim(TARGET_VIDEO_DOMAIN, 'http://') : $this->settings['videouploads']['host'], 'dir' => $this->dir_info['target_dir'], 'file_name' => $this->dir_info['output_filename'], 'img' => $img_info, 'type' => $vod_config['output_format'], 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'tran_server' => $tran_server, 'return' => 'success'); //请求用户提供的callback地址,并且携带用户提供的数据 if ($video['callback_url']) { if ($video['callback_data']) { $callback_data = json_decode(base64_decode($video['callback_data']), 1); //此处在视频库里面记录电视剧的id if ($callback_data['tv_play_id']) { $sql = "UPDATE " . DB_PREFIX . "vodinfo SET tv_play_id = '" . $callback_data['tv_play_id'] . "' WHERE id = '" . $vid . "'"; $this->db->query($sql); } $video_info['callback_data'] = $callback_data; } if ($callbackReturnData = $this->mediaserverCallback($video['callback_url'], $video_info)) { $callbackReturnData = json_decode($callbackReturnData, 1); if ($callbackReturnData['ErrorCode']) { $video_info['callback_return'] = $callbackReturnData; } else { $video_info['callback_return'] = $callbackReturnData[0]; } } } //可以接受用户传递的callback,这个callback是在转码完成之后回调 if ($video['after_callback_url']) { if ($video['callback_data']) { $callback_data = json_decode(base64_decode($video['callback_data']), 1); //此处在视频库里面记录电视剧的id if ($callback_data['tv_play_id']) { $sql = "UPDATE " . DB_PREFIX . "vodinfo SET tv_play_id = '" . $callback_data['tv_play_id'] . "' WHERE id = '" . $vid . "'"; $this->db->query($sql); } } //在data目录产生文件记录这个url $after_dir = DATA_DIR . 'after_callback_url/'; if (!hg_mkdir($after_dir) || !is_writeable($after_dir)) { $this->errorOutput(NOWRITE); } file_put_contents($after_dir . $vid . '.url', $video['after_callback_url']); } $this->addItem($video_info); $this->output(); } }
public function retranscode() { if (!$this->input['id']) { $this->errorOutput(NOID); } $id = intval($this->input['id']); $sql = " SELECT * FROM " . DB_PREFIX . "vodinfo WHERE id = {$id} "; $video = $this->db->query_first($sql); $output_tmp = explode('.', $video['video_filename']); //重新转码只针对源视频 if ($video['source_path']) { $source_path = rtrim($video['source_path'], '/') . '/' . $video['source_filename']; } else { $source_path = ''; } if (!is_file($video['source_base_path'] . $source_path) || !$source_path) { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$id}"; $this->db->query($sql); hg_do_transcode_fail($data, $id); //将转码失败的信息记录下来 $this->errorOutput(NOFILE); } //判断当前该视频是不是正在转码,如果正在转码就删除该任务 if ($t_server = checkStatusFromAllServers($id)) { $s_tran = new transcode($t_server); $s_tran->stop_transcode_task($id); } $vod_config = transcode_config(); //查询出视频转码的配置信息 if ($this->input['audit_auto']) { $this->settings['App_mediaserver']['extends'] = $this->input['audit_auto']; } //构建提交的转码配置 if (defined('SOBEY_SORTIDS') && SOBEY_SORTIDS) { if (in_array($video['vod_sort_id'], explode(',', SOBEY_SORTIDS))) { $this->input['mp4_from_sobey'] = 1; } } $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $data = array("sourceFile" => array(array('source' => $video['source_base_path'] . $source_path, 'start' => '0', 'duration' => '', 'is_water_marked' => '0')), "id" => "{$id}", "app_id" => APPID, "app_key" => APPKEY, "type" => "transcode_upload", "targetDir" => $video['video_base_path'] . $video['video_path'], "output_filename" => $output_tmp[0], "config" => $vod_config, "force_recodec" => $this->input['force_recodec'] ? '1' : '', "mp4_from_sobey" => $this->input['mp4_from_sobey'] ? '1' : '', "callback" => $this->settings['App_mediaserver'], "absolute_path" => '1'); //如果没传保持原来状态就将状态变成转码中 if (!$this->input['retain_status']) { $sql = "UPDATE " . DB_PREFIX . "vodinfo SET status = 0 WHERE id = {$id}"; $this->db->query($sql); } //如果是制定强制转码的话就要调取该视频第一次提交转码的时候的马赛克和水印配置 if (file_exists(UPLOAD_DIR . 'water/' . $id . '.json')) { $_param = file_get_contents(UPLOAD_DIR . 'water/' . $id . '.json'); $_param = json_decode($_param, 1); if ($data['force_recodec']) { if ($_param['mosaic']) { $data['config']['mosaic'] = $_param['mosaic']; } if ($_param['water']) { $data['config']['water_mark'] = $_param['water']['water_mark']; $data['config']['water_mark_x'] = $_param['water']['water_mark_x']; $data['config']['water_mark_y'] = $_param['water']['water_mark_y']; } } if ($_param['metadata']) { $data['metadata'] = $_param['metadata']; } } //选取转码服务器(此处强制转码与普通转码在选取服务器的时候有所不同) if ($data['force_recodec']) { $tran_server = select_assign_servers(true); } else { $tran_server = select_servers($id); } if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } $trans = new transcode($tran_server); //根据选取到转码服务器是否需要携带文件,选择各自的提交方式 if ($tran_server['need_file']) { $data['upload_file_in_callback'] = "1"; //$data['sourceFile'][0]['url'] = 'http://' . ltrim(SOURCE_VIDEO_DOMIAN,'http://') . '/' . $source_path; $data['sourceFile'][0]['url'] = 'http://' . ltrim(rtrim($video['source_hostwork'], '/'), 'http://') . '/' . $source_path; } $ret = $trans->addTranscodeTask($data); $return = json_decode($ret, 1); if ($return['return'] == 'fail') { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$id}"; $this->db->query($sql); hg_do_transcode_fail($data, $id); //将转码失败的信息记录下来 } //此处是处理强制转码之后删除json文件 if (file_exists(UPLOAD_DIR . 'water/' . $id . '.json') && $data['force_recodec']) { @unlink(UPLOAD_DIR . 'water/' . $id . '.json'); } echo $ret; }
private function videomark($type) { if (!$this->input['id']) { $this->errorOutput(NOID); //任务id } $vid = intval($this->input['id']); $start = $this->input['start']; //对应每个视频片段的开始时间 $duration = $this->input['duration']; //对应每个视频片段的时长 $source_dir = $this->input['source_dir']; //视频片段的原文件目录 $is_water_marked = $this->input['is_water_marked']; //视频片段的是否已经加过水印 $is_forcecode = $this->input['is_forcecode']; //标识视频是否已经经过强制转码 $video_base_path = $this->input['video_base_path']; //视频的基路径 if (!is_array($start)) { foreach (array("start", "duration", "source_dir") as $v) { ${$v} = array(${$v}); } } if (count($start) != count($duration) || count($start) != count($source_dir)) { $this->errorOutput(NOMATCH); } /****************查询视频配置信息*****************************/ $vod_config = transcode_config(); /***************配置一下转码完成之后视频的存放目录****************/ if ($type == 'transcode_mark') { //判断当前该视频是不是正在转码,如果正在转码就删除该任务 if ($t_server = checkStatusFromAllServers($vid)) { $s_tran = new transcode($t_server); $s_tran->stop_transcode_task($vid); } //拆条的时候要判断原视频是否正在转码中,如果正在转码中,暂时不拆条 $sql = "SELECT * FROM " . DB_PREFIX . "vodinfo WHERE id = '" . $vid . "'"; $cur_video = $this->db->query_first($sql); if ($cur_video['original_id']) { if (checkStatusFromAllServers($cur_video['original_id'])) { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$vid}"; $this->db->query($sql); $this->addLogs('拆条有误', '', '', '当前拆条的原视频正在转码中,该视频id:' . $vid); $this->errorOutput('当前拆条的原视频正在转码中,请稍后对该视频拆条'); } } $v_videodir = create_video_dir(); $vod_dir_names = $v_videodir[0]; $target_dir = $v_videodir[1]; $all_target_dir = TARGET_DIR . $target_dir; if (!hg_mkdir($all_target_dir) || !is_writeable($all_target_dir)) { $this->errorOutput(NOWRITE); } $output_filename = $vod_dir_names . ''; //为了兼容老版本 if (defined("TARGET_VIDEO_DOMAIN")) { $server_host = ltrim(TARGET_VIDEO_DOMAIN, 'http://'); } else { $server_host = $this->settings['videouploads']['host']; } $sql = " UPDATE " . DB_PREFIX . "vodinfo SET video_base_path = '" . TARGET_DIR . "', video_path = '" . $target_dir . "',video_filename = '" . $output_filename . "." . $vod_config['output_format'] . "',hostwork = 'http://" . $server_host . "' WHERE id = {$vid}"; $this->db->query($sql); } else { //快编的时候由于要覆盖原视频,所以$target_dir目录是原来视频的目录,从数据库查询 $sql = "SELECT video_base_path,video_path,video_filename,transcode_server FROM " . DB_PREFIX . "vodinfo WHERE id = {$vid}"; $arr = $this->db->query_first($sql); //检测该视频有没有被拆过条,如果有的话就不允许快编 if ($this->checkVideoIsSplit($vid)) { $this->addLogs('快编有误', '', '', '该视频已经有拆条不能快编,该视频id:' . $vid); $this->errorOutput('该视频已经有拆条不能快编'); } //判断当前该视频是不是正在转码,如果正在转码就删除该任务 foreach (array($vid, $vid . '_more') as $_vid) { if ($t_server = checkStatusFromAllServers($_vid)) { $s_tran = new transcode($t_server); $s_tran->stop_transcode_task($_vid); } } $target_dir = $arr['video_path']; $filename = explode('.', $arr['video_filename']); $output_filename = $filename[0]; if ($this->input['audit_auto']) { $this->settings['App_mediaserver']['extends'] = $this->input['audit_auto']; } $all_target_dir = $arr['video_base_path'] . $target_dir; } //更新当前清晰度,表明当前视频使用哪个转码配置进行转码的 $sql = " UPDATE " . DB_PREFIX . "vodinfo SET cur_clarity = '" . $vod_config['unique_id'] . "',status = 0,app_uniqueid = 'livmedia',mod_uniqueid = 'livmedia' WHERE id = {$vid}"; $this->db->query($sql); //选取转码服务器 $tran_server = select_servers($vid); if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } $source_conf = array(); foreach ($source_dir as $k => $v) { $source_conf[] = array('source' => $video_base_path[$k] . $source_dir[$k], 'start' => $start[$k], 'duration' => $duration[$k], 'is_water_marked' => $is_water_marked[$k], 'is_recodec' => $is_forcecode[$k], 'url' => $tran_server['need_file'] ? defined("TARGET_VIDEO_DOMAIN") ? 'http://' . ltrim(TARGET_VIDEO_DOMAIN, 'http://') . '/' . $source_dir[$k] : $this->settings['videouploads']['protocol'] . $this->settings['videouploads']['host'] . '/' . $source_dir[$k] : ''); } /**************用curl将视频连同转码参数一并提交过去****************/ $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $data = array("sourceFile" => $source_conf, "id" => "{$vid}", "app_id" => APPID, "app_key" => APPKEY, "type" => $type, "targetDir" => $all_target_dir, "output_filename" => $output_filename, "config" => $vod_config, "callback" => $this->settings['App_mediaserver'], "absolute_path" => '1'); //根据选取到转码服务器是否需要携带文件,选择各自的提交方式 if ($tran_server['need_file']) { $data['upload_file_in_callback'] = "1"; } //头信息 if ($this->settings['metadata']) { $metadata = $this->settings['metadata']; foreach ($metadata as $k => $v) { if (!$v) { unset($metadata[$k]); } else { $metadata[$k] = urlencode($v); } } $data['metadata'] = $metadata; } $trans = new transcode($tran_server); $ret = $trans->addTranscodeTask($data); $return = json_decode($ret, 1); if ($return['return'] == 'fail') { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$vid}"; $this->db->query($sql); hg_do_transcode_fail($data, $vid); //将转码失败的信息记录下来 } echo $ret; }
public function submit_transcode($video, $target, $output_filename, $vid, $img_info) { //构建提交转码的参数 $vod_config = transcode_config(); //$video = $this->input; $source_arr = array('source' => UPLOAD_DIR . $video['filepath'], 'start' => '0', 'duration' => '', 'is_water_marked' => '0'); $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $data = array("sourceFile" => array($source_arr), "id" => $vid, "app_id" => APPID, "app_key" => APPKEY, "type" => "transcode_upload", "targetDir" => TARGET_DIR . $target, "output_filename" => $output_filename, "config" => $vod_config, "callback" => $this->settings['App_mediaserver'], "ts_need_preprocess" => $video['ts_need_preprocess'] ? '1' : '0', "mp4_from_sobey" => $video['mp4_from_sobey'] ? '1' : '0', "force_recodec" => $video['force_recodec'] ? '1' : '0', "absolute_path" => '1'); //头信息 if ($this->settings['metadata']) { $metadata = $this->settings['metadata']; foreach ($metadata as $k => $v) { if (!$v) { unset($metadata[$k]); } else { $metadata[$k] = urlencode($v); } } $data['metadata'] = $metadata; } //选取转码服务器 if ($video['server_id']) { $tran_server = select_servers_by_id($video['server_id'], $vid); } else { $tran_server = select_servers($vid); //自动选择转码服务器 } if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } $trans = new transcode($tran_server); //根据选取到转码服务器是否需要携带文件,选择各自的提交方式 if ($tran_server['need_file']) { $data['upload_file_in_callback'] = "1"; $data['sourceFile'][0]['url'] = 'http://' . ltrim(SOURCE_VIDEO_DOMIAN, 'http://') . '/' . $source_arr['source']; } $ret = $trans->addTranscodeTask($data); $return = json_decode($ret, 1); if ($return['return'] == 'fail') { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$vid}"; $this->db->query($sql); hg_do_transcode_fail($data, $vid); //将转码失败的信息记录下来 $error_info = array('return' => 'success', 'transcode' => 'fail', 'id' => $vid, 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'img' => $img_info, 'ErrorCode' => '0x0025', 'ErrorText' => '提交转码失败'); echo json_encode($error_info); //上传成功,转码失败 } else { //返回数据 $video_info = array('id' => $vid, 'protocol' => 'http://', 'host' => defined("TARGET_VIDEO_DOMAIN") ? ltrim(TARGET_VIDEO_DOMAIN, 'http://') : $this->settings['videouploads']['host'], 'dir' => $target, 'file_name' => $output_filename, 'img' => $img_info, 'type' => $vod_config['output_format'], 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'return' => 'success'); return $video_info; /***************************** //请求用户提供的callback地址,并且携带用户提供的数据 if($video['callback_url']) { if($video['callback_data']) { $callback_data = json_decode(base64_decode($video['callback_data']),1); //此处在视频库里面记录电视剧的id if($callback_data['tv_play_id']) { $sql = "UPDATE " . DB_PREFIX ."vodinfo SET tv_play_id = '" . $callback_data['tv_play_id'] . "' WHERE id = '" .$vid. "'"; $this->db->query($sql); } $video_info['callback_data'] = $callback_data; } if($callbackReturnData = $this->mediaserverCallback($video['callback_url'],$video_info)) { $callbackReturnData = json_decode($callbackReturnData,1); if($callbackReturnData['ErrorCode']) { $video_info['callback_return'] = $callbackReturnData; } else { $video_info['callback_return'] = $callbackReturnData[0]; } } } //可以接受用户传递的callback,这个callback是在转码完成之后回调 if($video['after_callback_url']) { //在data目录产生文件记录这个url $after_dir = DATA_DIR . 'after_callback_url/'; if (!hg_mkdir($after_dir) || !is_writeable($after_dir)) { $this->errorOutput(NOWRITE); } file_put_contents($after_dir . $vid . '.url',$video['after_callback_url']); } $this->addItem($video_info); $this->output(); *****************************/ } }
public function run() { //在转码服务器空闲的时候进行多码流 /* $route = select_servers();//选取服务器 if(!$route) { $this->errorOutput(NO_SELECT_TRANSERVER); } $transcode = new transcode($route); $task_info = json_decode($transcode->get_transcode_tasks(),1); if($task_info['transcoding_tasks']) { $this->errorOutput(EXECAFTERMOREBIT); } */ //先选取转码服务器 /* if(defined('MORE_BITRATE_SERVER') && MORE_BITRATE_SERVER)//指定转码服务器 { $tran_server = select_servers_by_id(intval(MORE_BITRATE_SERVER)); } else { //$tran_server = select_servers($vid);//自动选择转码服务器 $this->errorOutput('没有可用于多码流的服务器'); } */ //选取用于多码流的服务器 $tran_server = select_assign_servers(); if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } //先找出视频需要多码流的视频(排除转码中与暂停状态的视频以及失败的视频) $sql = "SELECT * FROM " . DB_PREFIX . "vodinfo WHERE morebitrate_config_id != '' AND is_morebitrate=0 AND status NOT IN (0,4,-1,5) ORDER BY create_time DESC LIMIT 0,2"; $q = $this->db->query($sql); $videos = array(); while ($r = $this->db->fetch_array($q)) { $videos[$r['id']] = $r; } $task_ids = array(); //记录任务反馈 if (!$videos) { $this->errorOutput(NOVIDEOS); } //判断选取的视频在不在多码流转码中,在的话就不提交这个视频了 foreach ($videos as $k => $v) { if (checkStatusFromAllServers($k . '_more') || checkStatusFromAllServers($k)) { unset($videos[$k]); } } if (!$videos) { $this->errorOutput(NOVIDEOS); } //$transcode_configs = get_transcode_configs($config_id); foreach ($videos as $kk => $video) { //采用转码之后的视频 $video_source = rtrim($video['video_path'], '/') . '/' . $video['video_filename']; //构建target的目录 $output_file = array(); $clarityUniqueId = array(); //记录清晰度标识 $transcode_configs = get_transcode_configs($video['morebitrate_config_id']); if (!$transcode_configs) { $this->errorOutput(NO_DATA); } //如果获取的转码配置个数小于1,就不执行了 if (count($transcode_configs) < 1) { $this->errorOutput(NOMOREBITRATE); } //array_shift($transcode_configs); foreach ($transcode_configs as $k => $v) { if ($v['unique_id'] == $video['cur_clarity']) { continue; } $target_dir_info = pathinfo(rtrim($video['video_path'], '/')); $new_target_dir = $target_dir_info['dirname'] . '/' . $v['unique_id'] . '_' . $target_dir_info['basename']; if (!hg_mkdir($video['video_base_path'] . $new_target_dir) || !is_writeable($video['video_base_path'] . $new_target_dir)) { $this->errorOutput(NOWRITE); } $output_file[] = array('targetDir' => $video['video_base_path'] . $new_target_dir, 'output_filename' => $v['unique_id'] . '_' . $target_dir_info['filename'], 'config' => $v); $clarityUniqueId[] = $v['unique_id']; } if ($tran_server['need_file']) { /* if(defined("TARGET_VIDEO_DOMAIN")) { $url = 'http://' . ltrim(TARGET_VIDEO_DOMAIN,'http://') . '/' . $video_source; } else { $url = $this->settings['videouploads']['protocol'] . $this->settings['videouploads']['host'] . '/' . $video_source; } */ $url = 'http://' . ltrim(rtrim($video['hostwork'], '/'), 'http://') . '/' . $video_source; } else { $url = ''; } $sourceFile = array(); $sourceFile[] = array('source' => $video['video_base_path'] . $video_source, 'start' => '0', 'duration' => '', 'is_water_marked' => '0', 'url' => $url); //构建提交转码的数据 $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $this->settings['App_mediaserver']['filename'] = 'more_bitrate_callback.php'; //设置多码流回调 $data = array("sourceFile" => $sourceFile, "id" => $video['id'] . '_more', "app_id" => APPID, "app_key" => APPKEY, "type" => 'transcode_multi_bitrate', "outputFile" => $output_file, "callback" => $this->settings['App_mediaserver'], "absolute_path" => '1'); //头信息 if ($this->settings['metadata']) { $metadata = $this->settings['metadata']; foreach ($metadata as $k => $v) { if (!$v) { unset($metadata[$k]); } else { $metadata[$k] = urlencode($v); } } $data['metadata'] = $metadata; } $trans = new transcode($tran_server); $ret = $trans->addTranscodeTask($data); //提交后更新清晰度字段 $sql = "UPDATE " . DB_PREFIX . "vodinfo SET clarity = '" . serialize($clarityUniqueId) . "',is_morebitrate=1 WHERE id = '" . $video['id'] . "'"; $this->db->query($sql); $return = json_decode($ret, 1); if ($return['return'] == 'fail') { $this->addLogs('提交多码流', $data, $return, '提交多码流,视频id:' . $return['id']); } $task_ids[] = $return; } $this->addItem($task_ids); $this->output(); }
public function submit_transcode() { //构建提交转码的参数 $vod_config = transcode_config(); $is_file = 0; //标识是否是文件上传 if ($_FILES) { $is_file = 1; $this->check_has_videofile($vod_config); $this->input['filepath'] = $this->dir_info['filepath']; } else { if (!$this->input['notcheck']) { if (!$this->input['filepath'] || !file_exists(UPLOAD_DIR . $this->input['filepath'])) { $this->errorOutput(NOTFINDFILE); } } //如果没传title就取文件名 if (!$this->input['title']) { $_path_name = basename($this->input['filepath']); $this->input['title'] = substr($_path_name, 0, strrpos($_path_name, '.')); } $this->create_dir($vod_config); } $video = $this->input; $v_vinfo = $this->storage_data($video, $vod_config); $vid = $v_vinfo['vid']; $img_info = $v_vinfo['img_info']; if ($video['audit_auto']) { $this->settings['App_mediaserver']['extends'] = $video['audit_auto']; } //传到转码服务器的duration参数的单位是秒,所以此处因为接受外部的时间单位是ms if ($is_file) { $duration = ''; $start = '0'; } else { $duration = $video['duration'] ? $video['duration'] : intval($video['end'] - $video['start']) / 1000 . ''; $start = $video['start']; } $source_arr = array('source' => UPLOAD_DIR . $video['filepath'], 'start' => $start, 'duration' => $duration, 'is_water_marked' => '0'); $this->settings['App_mediaserver']['dir'] = $this->settings['App_mediaserver']['dir'] . 'admin/'; $data = array("sourceFile" => array($source_arr), "id" => "{$vid}", "app_id" => APPID, "app_key" => APPKEY, "type" => "transcode_upload", "targetDir" => TARGET_DIR . $this->dir_info['target_dir'], "output_filename" => $this->dir_info['output_filename'], "config" => $vod_config, "callback" => $this->settings['App_mediaserver'], "ts_need_preprocess" => $video['ts_need_preprocess'] ? '1' : '0', "mp4_from_sobey" => $video['mp4_from_sobey'] ? '1' : '0', "force_recodec" => $video['force_recodec'] ? '1' : '0', "absolute_path" => '1'); //加马赛克(优先采用用户提供的自定义的马赛克) if ($video['mosaic']) { $mosaic = explode(',', $video['mosaic']); if (count($mosaic) == 4) { $mosaicArr = array('x' => $mosaic[0], 'y' => $mosaic[1], 'width' => $mosaic[2], 'height' => $mosaic[3]); $data['config']['mosaic'] = $mosaicArr; } } elseif ($video['mosaic_id']) { $mosaic_mode = new mosaic_mode(); $mosaic_config = $mosaic_mode->detail($video['mosaic_id']); if ($mosaic_config) { $data['config']['mosaic'] = array('x' => $mosaic_config['x'], 'y' => $mosaic_config['y'], 'width' => $mosaic_config['width'], 'height' => $mosaic_config['height']); } } //指定不用加水印 if ($video['no_water']) { $data['config']['water_mark'] = ''; } else { if ($video['water_id']) { $water_mode = new water_config_mode(); $waterInfo = $water_mode->detail($video['water_id']); if ($waterInfo) { $data['config']['water_mark'] = $waterInfo['base_path'] . $waterInfo['img_path']; if ($video['water_pos']) { $_pos = explode(',', $video['water_pos']); } else { $_pos = explode(',', WATER_POS); //如果没传位置,就用默认位置 } $data['config']['water_mark_x'] = $_pos[0]; $data['config']['water_mark_y'] = $_pos[1]; } } } //头信息 if ($this->settings['metadata']) { $metadata = $this->settings['metadata']; foreach ($metadata as $k => $v) { if (!$v) { unset($metadata[$k]); } else { $metadata[$k] = urlencode($v); } } $data['metadata'] = $metadata; } //记录水印与马赛克的参数,在强制转码的时候可能会用到这些参数,因为在第一次转码的时候不一定是强制转码,这样水印与马赛克不一定有 $_param = array('mosaic' => $data['config']['mosaic'], 'water' => array('water_mark' => $data['config']['water_mark'], 'water_mark_x' => $data['config']['water_mark_x'], 'water_mark_y' => $data['config']['water_mark_y']), 'metadata' => $data['metadata']); file_put_contents(DATA_DIR . $vid . '.json', json_encode($_param)); //选取转码服务器 if ($video['server_id']) { $tran_server = select_servers_by_id($video['server_id'], $vid); } else { $tran_server = select_servers($vid); //自动选择转码服务器 } if (!$tran_server) { $this->errorOutput(NO_SELECT_TRANSERVER); } $trans = new transcode($tran_server); //根据选取到转码服务器是否需要携带文件,选择各自的提交方式 if ($tran_server['need_file']) { $data['upload_file_in_callback'] = "1"; $data['sourceFile'][0]['url'] = 'http://' . ltrim(SOURCE_VIDEO_DOMIAN, 'http://') . '/' . $source_arr['source']; } $ret = $trans->addTranscodeTask($data); $return = json_decode($ret, 1); if ($return['return'] == 'fail') { $sql = " UPDATE " . DB_PREFIX . "vodinfo SET status = -1 WHERE id = {$vid}"; $this->db->query($sql); hg_do_transcode_fail($data, $vid); //将转码失败的信息记录下来 $error_info = array('return' => 'success', 'transcode' => 'fail', 'id' => $vid, 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'img' => $img_info, 'ErrorCode' => '0x0025', 'ErrorText' => '提交转码失败'); echo json_encode($error_info); //上传成功,转码失败 } else { //返回数据 $video_info = array('id' => $vid, 'protocol' => 'http://', 'host' => defined("TARGET_VIDEO_DOMAIN") ? ltrim(TARGET_VIDEO_DOMAIN, 'http://') : $this->settings['videouploads']['host'], 'dir' => $this->dir_info['target_dir'], 'file_name' => $this->dir_info['output_filename'], 'img' => $img_info, 'type' => $vod_config['output_format'], 'app' => APP_UNIQUEID, 'module' => MOD_UNIQUEID, 'return' => 'success'); //请求用户提供的callback地址,并且携带用户提供的数据 if ($video['callback_url']) { if ($video['callback_data']) { $callback_data = json_decode(base64_decode($video['callback_data']), 1); //此处在视频库里面记录电视剧的id if ($callback_data['tv_play_id']) { $sql = "UPDATE " . DB_PREFIX . "vodinfo SET tv_play_id = '" . $callback_data['tv_play_id'] . "' WHERE id = '" . $vid . "'"; $this->db->query($sql); } $video_info['callback_data'] = $callback_data; } if ($callbackReturnData = $this->mediaserverCallback($video['callback_url'], $video_info)) { $callbackReturnData = json_decode($callbackReturnData, 1); if ($callbackReturnData['ErrorCode']) { $video_info['callback_return'] = $callbackReturnData; } else { $video_info['callback_return'] = $callbackReturnData[0]; } } } $this->addItem($video_info); $this->output(); } }