From f6337ce92ece8716c0b7d2df336c23a4fce7db28 Mon Sep 17 00:00:00 2001 From: filesite Date: Fri, 29 Nov 2024 13:07:24 +0800 Subject: [PATCH] improve m3u8 file play --- plugins/Common.php | 7 +++ .../beauty/controller/CommandController.php | 12 +++-- themes/beauty/controller/M3u8Controller.php | 48 +++++++++++++++---- themes/beauty/controller/SiteController.php | 5 +- themes/beauty/views/list/bydate.php | 4 +- 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/plugins/Common.php b/plugins/Common.php index 31a324e..540f56d 100644 --- a/plugins/Common.php +++ b/plugins/Common.php @@ -797,4 +797,11 @@ Class Common { return !empty($file['fstat']['mtime']) && !empty($file['fstat']['ctime']) ? min($file['fstat']['mtime'], $file['fstat']['ctime']) : 0; } + //根据文件id、索引分批存储数量,返回当前文件所属索引序号 + public static function getIndexNumByFileId($id, $dirNum) { + $firstChar = substr($id, 0, 1); + $ascNum = ord($firstChar); + return $ascNum % $dirNum; + } + } \ No newline at end of file diff --git a/themes/beauty/controller/CommandController.php b/themes/beauty/controller/CommandController.php index 4e1fac8..31ca4d1 100644 --- a/themes/beauty/controller/CommandController.php +++ b/themes/beauty/controller/CommandController.php @@ -354,13 +354,12 @@ eof; return Common::setCache($cacheKey, $cacheData); } + //根据文件id首字母以及需要分批存储的数量,来对文件进行分组 protected function getFilesByFirstCharcter($files, $dirNum) { $byFirst = []; foreach ($files as $id => $item) { - $firstChar = substr($id, 0, 1); - $ascNum = ord($firstChar); - $index = $ascNum % $dirNum; + $index = Common::getIndexNumByFileId($id, $dirNum); if (empty($byFirst[$index])) { $byFirst[$index] = []; } @@ -392,6 +391,13 @@ eof; Common::saveCacheToFile("{$cacheKey}_{$i}", $filesByFirstChar[$i-1], $cacheDir); } + //保存文件总数,以及分批数量,以便前端根据id来索引数据 + $statsData = [ + 'filetotal' => $total, + 'dirnum' => $dirNum, + ]; + Common::saveCacheToFile("{$cacheKey}_stats", $statsData, $cacheDir); + return true; } diff --git a/themes/beauty/controller/M3u8Controller.php b/themes/beauty/controller/M3u8Controller.php index f288018..ddbfc04 100644 --- a/themes/beauty/controller/M3u8Controller.php +++ b/themes/beauty/controller/M3u8Controller.php @@ -7,33 +7,37 @@ require_once __DIR__ . '/../../../plugins/Parsedown.php'; require_once __DIR__ . '/../../../plugins/Common.php'; Class M3u8Controller extends Controller { + protected $allFilesCacheKey = 'MainBotAllFiles'; //参数 //@id - 文件id //@cid - 数据缓存id //支持nginx secure防盗链:md5={$md5}&expires={$expires} + //支持只传video id,从索引数据中获取文件信息 public function actionIndex() { $videoId = $this->get('id', ''); $cacheParentDataId = $this->get('cid', ''); - if (empty($videoId) || empty($cacheParentDataId)) { + if (empty($videoId)) { throw new Exception("参数缺失!", 403); } //TODO: 防盗链检查 - //渲染m3u8内容 - $cacheSeconds = 86400; - $cachedParentData = Common::getCacheFromFile($cacheParentDataId, $cacheSeconds); - if (empty($cachedParentData)) { - $err = '缓存数据已失效,如果重新点击目录依然打不开,请联系管理员。'; - throw new Exception($err, 404); + if (!empty($cacheParentDataId)) { + $cacheSeconds = 86400; + $cachedParentData = Common::getCacheFromFile($cacheParentDataId, $cacheSeconds); + if (empty($cachedParentData)) { + $err = '缓存数据已失效,如果重新点击目录依然打不开,请联系管理员。'; + throw new Exception($err, 404); + } } - if (empty($cachedParentData[$videoId])) { + if (!empty($cachedParentData) && empty($cachedParentData[$videoId])) { $erro = "缓存数据中找不到当前视频,请返回上一页重新进入!"; throw new Exception($err, 404); - }else if (!empty($cachedParentData)) { + }else if (!empty($cachedParentData[$videoId])) { + //渲染m3u8内容 $m3u8 = $cachedParentData[$videoId]; $m3u8Content = $this->getM3u8Content($m3u8['realpath'], $cachedParentData); if (!empty($m3u8Content)) { @@ -42,6 +46,32 @@ Class M3u8Controller extends Controller { $err = 'm3u8内容为空!'; throw new Exception($err, 500); } + }else { //尝试从索引数据中获取文件信息 + $expireSeconds = 86400 * 365; //缓存 365 天 + $cacheData = Common::getCacheFromFile($this->allFilesCacheKey . '_stats', $expireSeconds); + if (!empty($cacheData)) { + $dirNum = $cacheData['dirnum']; + $index = Common::getIndexNumByFileId($videoId, $dirNum) + 1; + $cacheKey = $this->allFilesCacheKey . "_{$index}"; + $cacheFiles = Common::getCacheFromFile($cacheKey, $expireSeconds); + + if (!empty($cacheFiles[$videoId])) { + $m3u8 = $cacheFiles[$videoId]; + $m3u8Content = $this->getM3u8Content($m3u8['realpath']); + if (!empty($m3u8Content)) { + return $this->renderM3u8($m3u8Content); + }else { + $err = 'm3u8内容为空!'; + throw new Exception($err, 500); + } + }else { + $err = '索引数据中找不到此视频!'; + throw new Exception($err, 500); + } + }else { + $err = '没有索引数据,请参考文档生成索引!'; + throw new Exception($err, 500); + } } } diff --git a/themes/beauty/controller/SiteController.php b/themes/beauty/controller/SiteController.php index 18bb08c..6cee013 100644 --- a/themes/beauty/controller/SiteController.php +++ b/themes/beauty/controller/SiteController.php @@ -811,7 +811,8 @@ Class SiteController extends Controller { $page = $this->get('page', 1); $pageSize = $this->get('limit', 100); - if (empty($videoUrl) || empty($videoId) || empty($cateId) || empty($cacheParentDataId)) { + // || empty($cacheParentDataId) + if (empty($videoUrl) || empty($videoId) || empty($cateId)) { throw new Exception("缺少参数!", 403); } @@ -822,7 +823,7 @@ Class SiteController extends Controller { $videoExtension = pathinfo($arr['path'], PATHINFO_EXTENSION); //支持m3u8地址:/m3u8/?id=xxx - if ($videoFilename == 'm3u8') { + if ($videoFilename == 'm3u8' && !empty($cacheParentDataId)) { $videoExtension = 'm3u8'; //从缓存数据获取文件名 diff --git a/themes/beauty/views/list/bydate.php b/themes/beauty/views/list/bydate.php index f110e71..1085a77 100644 --- a/themes/beauty/views/list/bydate.php +++ b/themes/beauty/views/list/bydate.php @@ -250,12 +250,12 @@ eof; }else if (in_array($file['extension'], $videoExts)) { //输出视频 //m3u8支持 if ($file['extension'] == 'm3u8') { - $videoUrl = urlencode("{$file['path']}&cid={$viewData['cacheDataId']}"); + $videoUrl = urlencode("{$file['path']}"); }else { $videoUrl = urlencode($file['path']); } - $linkUrl = "/site/player?id={$file['id']}&pid={$file['pid']}&cid={$viewData['cacheDataId']}&url={$videoUrl}"; + $linkUrl = "/site/player?id={$file['id']}&pid={$file['pid']}&url={$videoUrl}"; if ($viewData['showType'] == 'video') { $linkUrl .= "&page={$viewData['page']}&limit={$viewData['pageSize']}"; }