<?php /** * Created by PhpStorm. * User: liyifei2012it * Date: 17/4/13 * Time: 11:38 */ namespace Frontend\Controller\Callback; use Think\Log; use VcySDK\Service; use VcySDK\Cron; use VcySDK\FileConvert; use Common\Common\Constant; use Common\Service\SourceService; use Common\Service\SourceAttachService; use Common\Service\TaskService; class CheckAttachController extends AbstractController { /** * 检查附件(视频转码、文件转换)计划任务回调接口 * @author zhonglei */ public function Index() { Log::record(sprintf('---%s %s CheckAttach START---', QY_DOMAIN, APP_IDENTIFIER), Log::INFO); $source_id = I('get.source_id', 0, 'intval'); $cron_id = I('get.cron_id', '', 'trim'); if (empty($cron_id) || empty($source_id)) { $this->_exit(); } // 业务未找到任务,退出并删除传参过来的当前计划任务 $taskServ = new TaskService(); $task = $taskServ->get_by_conds(['source_id' => $source_id]); if (empty($task)) { Log::record("not found task, source_id: {$source_id}", Log::INFO); // 删除UC计划任务 $this->_delCron($cron_id); } // 未找到素材,删除计划任务 $cron_id = $task['cron_id']; $sourceServ = new SourceService(); $source = $sourceServ->get($source_id); if (empty($source)) { Log::record("not found source, source_id: {$source_id}", Log::INFO); $this->_delTask($source_id, $cron_id); } // 未找到附件,删除计划任务 $attachServ = new SourceAttachService(); $source_attachs = $attachServ->list_by_conds(['source_id' => $source_id]); if (empty($source_attachs)) { // 将素材状态修改为正常 $sourceServ->update($source_id, ['source_status' => Constant::SOURCE_STATUS_NORMAL]); Log::record("not found attach, source_id: {$source_id}", Log::INFO); $this->_delTask($source_id, $cron_id); } $convert_status = Constant::SOURCE_STATUS_CONVERT; $convertServ = new FileConvert(Service::instance()); foreach ($source_attachs as $source_attach) { // 已完成 if (!empty($source_attach['at_convert_url'])) { continue; } $at_convert_url = ''; $at_cover_url = ''; switch ($source_attach['at_type']) { // 视频 case Constant::ATTACH_TYPE_VIDEO: $result = $convertServ->getVodPlayUrl($source_attach['at_id']); if (is_array($result) && (isset($result['url']) || isset($result['hd']))) { // 转码后的视频url $at_convert_url = str_replace('http://', '//', (!empty($result['hd']) ? $result['hd'] : $result['url'])); $at_convert_url = str_replace('https://', '//', $at_convert_url); // 视频封面地址(5秒内会生成) // FIXME 因前端技术实现难点,视频第一帧做为封面需求暂时废弃(2018-01-03)。视频第一帧图片先做存储,等待前端攻克技术难题后使用 $at_cover_url = str_replace('http://', '//', $result['coverUrl']); $at_cover_url = str_replace('https://', '//', $at_cover_url); $convert_status = Constant::SOURCE_STATUS_NORMAL; } break; // 文件 case Constant::ATTACH_TYPE_FILE: $result = $convertServ->get($source_attach['at_id']); if (is_array($result) && isset($result['caConvertStatus'])) { // 转码成功 if (FileConvert::CONVERT_STATUS_SUCCESS == $result['caConvertStatus']) { $at_convert_url = $result['caAttachment']; $convert_status = Constant::SOURCE_STATUS_NORMAL; } // 转码失败(状态不是:待处理、转码中、成功,即为失败) $normalStatus = [ FileConvert::CONVERT_STATUS_WATTING, FileConvert::CONVERT_STATUS_ING, FileConvert::CONVERT_STATUS_SUCCESS, ]; if (!in_array($result['caConvertStatus'], $normalStatus)) { $convert_status = Constant::SOURCE_STATUS_FAIL; } } break; } // 转码成功时,修改转码后url if (!empty($at_convert_url)) { // 待更新数据 $update_data['at_convert_url'] = $at_convert_url; // 视频封面地址不为空,存储视频封面 if (!empty($at_cover_url)) { $update_data['at_cover_url'] = $at_cover_url; } $attachServ->update($source_attach['source_attach_id'], $update_data); Log::record("convert success, source_attach_id: {$source_attach['source_attach_id']}, at_convert_url: {$at_convert_url}", Log::INFO); } } // 更新素材状态、结束任务 if ($convert_status != Constant::SOURCE_STATUS_CONVERT) { // 重置转码状态 $successAttachs = $attachServ->count_by_conds(['source_id' => $source_id, 'at_convert_url != ?' => '']); if ($successAttachs != count($source_attachs) && Constant::SOURCE_STATUS_NORMAL == $convert_status) { $convert_status = Constant::SOURCE_STATUS_CONVERT; } $sourceServ->update($source_id, ['source_status' => $convert_status]); Log::record("update source_status, source: {$source_id}", Log::INFO); // 所有任务转码完成 或 转码失败,结束本地任务 if ($successAttachs == count($source_attachs) || Constant::SOURCE_STATUS_FAIL == $convert_status) { $this->_delTask($source_id, $cron_id); } } // 结束回调 $this->_exit(); } /** * 退出 * @author zhonglei * @return void */ private function _exit() { // 日志结束 Log::record(sprintf('---%s %s CheckAttach END---', QY_DOMAIN, APP_IDENTIFIER), Log::INFO); exit('SUCCESS'); } /** * 删除计划任务并退出 * @author zhonglei * @param int $source_id 素材ID * @param string $cron_id UC计划任务ID * @return void */ private function _delTask($source_id, $cron_id) { // 删除业务计划任务记录 $taskServ = new TaskService(); $taskServ->delete_by_conds([ 'source_id' => $source_id, 'cron_id' => $cron_id, ]); // 删除UC计划任务 $this->_delCron($cron_id); } /** * 删除UC计划任务 * @param string $cron_id 计划任务ID * @return void */ private function _delCron($cron_id) { $cronSdk = new Cron(Service::instance()); try { // 删除计划任务 $cronSdk->delete($cron_id); } catch (\Exception $e) { Log::record('uc delete cron fail: cron_id=' . $cron_id . ', msg=' . $e->getMessage(), Log::ERR); } $this->_exit(); } }