Browse Source

improve m3u8 file play

master
filesite 1 day ago
parent
commit
f6337ce92e
  1. 7
      plugins/Common.php
  2. 12
      themes/beauty/controller/CommandController.php
  3. 38
      themes/beauty/controller/M3u8Controller.php
  4. 5
      themes/beauty/controller/SiteController.php
  5. 4
      themes/beauty/views/list/bydate.php

7
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; 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;
}
} }

12
themes/beauty/controller/CommandController.php

@ -354,13 +354,12 @@ eof;
return Common::setCache($cacheKey, $cacheData); return Common::setCache($cacheKey, $cacheData);
} }
//根据文件id首字母以及需要分批存储的数量,来对文件进行分组
protected function getFilesByFirstCharcter($files, $dirNum) { protected function getFilesByFirstCharcter($files, $dirNum) {
$byFirst = []; $byFirst = [];
foreach ($files as $id => $item) { foreach ($files as $id => $item) {
$firstChar = substr($id, 0, 1); $index = Common::getIndexNumByFileId($id, $dirNum);
$ascNum = ord($firstChar);
$index = $ascNum % $dirNum;
if (empty($byFirst[$index])) { if (empty($byFirst[$index])) {
$byFirst[$index] = []; $byFirst[$index] = [];
} }
@ -392,6 +391,13 @@ eof;
Common::saveCacheToFile("{$cacheKey}_{$i}", $filesByFirstChar[$i-1], $cacheDir); Common::saveCacheToFile("{$cacheKey}_{$i}", $filesByFirstChar[$i-1], $cacheDir);
} }
//保存文件总数,以及分批数量,以便前端根据id来索引数据
$statsData = [
'filetotal' => $total,
'dirnum' => $dirNum,
];
Common::saveCacheToFile("{$cacheKey}_stats", $statsData, $cacheDir);
return true; return true;
} }

38
themes/beauty/controller/M3u8Controller.php

@ -7,33 +7,37 @@ require_once __DIR__ . '/../../../plugins/Parsedown.php';
require_once __DIR__ . '/../../../plugins/Common.php'; require_once __DIR__ . '/../../../plugins/Common.php';
Class M3u8Controller extends Controller { Class M3u8Controller extends Controller {
protected $allFilesCacheKey = 'MainBotAllFiles';
//参数 //参数
//@id - 文件id //@id - 文件id
//@cid - 数据缓存id //@cid - 数据缓存id
//支持nginx secure防盗链:md5={$md5}&expires={$expires} //支持nginx secure防盗链:md5={$md5}&expires={$expires}
//支持只传video id,从索引数据中获取文件信息
public function actionIndex() { public function actionIndex() {
$videoId = $this->get('id', ''); $videoId = $this->get('id', '');
$cacheParentDataId = $this->get('cid', ''); $cacheParentDataId = $this->get('cid', '');
if (empty($videoId) || empty($cacheParentDataId)) { if (empty($videoId)) {
throw new Exception("参数缺失!", 403); throw new Exception("参数缺失!", 403);
} }
//TODO: 防盗链检查 //TODO: 防盗链检查
//渲染m3u8内容 if (!empty($cacheParentDataId)) {
$cacheSeconds = 86400; $cacheSeconds = 86400;
$cachedParentData = Common::getCacheFromFile($cacheParentDataId, $cacheSeconds); $cachedParentData = Common::getCacheFromFile($cacheParentDataId, $cacheSeconds);
if (empty($cachedParentData)) { if (empty($cachedParentData)) {
$err = '缓存数据已失效,如果重新点击目录依然打不开,请联系管理员。'; $err = '缓存数据已失效,如果重新点击目录依然打不开,请联系管理员。';
throw new Exception($err, 404); throw new Exception($err, 404);
} }
}
if (empty($cachedParentData[$videoId])) { if (!empty($cachedParentData) && empty($cachedParentData[$videoId])) {
$erro = "缓存数据中找不到当前视频,请返回上一页重新进入!"; $erro = "缓存数据中找不到当前视频,请返回上一页重新进入!";
throw new Exception($err, 404); throw new Exception($err, 404);
}else if (!empty($cachedParentData)) { }else if (!empty($cachedParentData[$videoId])) {
//渲染m3u8内容
$m3u8 = $cachedParentData[$videoId]; $m3u8 = $cachedParentData[$videoId];
$m3u8Content = $this->getM3u8Content($m3u8['realpath'], $cachedParentData); $m3u8Content = $this->getM3u8Content($m3u8['realpath'], $cachedParentData);
if (!empty($m3u8Content)) { if (!empty($m3u8Content)) {
@ -42,6 +46,32 @@ Class M3u8Controller extends Controller {
$err = 'm3u8内容为空!'; $err = 'm3u8内容为空!';
throw new Exception($err, 500); 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);
}
} }
} }

5
themes/beauty/controller/SiteController.php

@ -811,7 +811,8 @@ Class SiteController extends Controller {
$page = $this->get('page', 1); $page = $this->get('page', 1);
$pageSize = $this->get('limit', 100); $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); throw new Exception("缺少参数!", 403);
} }
@ -822,7 +823,7 @@ Class SiteController extends Controller {
$videoExtension = pathinfo($arr['path'], PATHINFO_EXTENSION); $videoExtension = pathinfo($arr['path'], PATHINFO_EXTENSION);
//支持m3u8地址:/m3u8/?id=xxx //支持m3u8地址:/m3u8/?id=xxx
if ($videoFilename == 'm3u8') { if ($videoFilename == 'm3u8' && !empty($cacheParentDataId)) {
$videoExtension = 'm3u8'; $videoExtension = 'm3u8';
//从缓存数据获取文件名 //从缓存数据获取文件名

4
themes/beauty/views/list/bydate.php

@ -250,12 +250,12 @@ eof;
}else if (in_array($file['extension'], $videoExts)) { //输出视频 }else if (in_array($file['extension'], $videoExts)) { //输出视频
//m3u8支持 //m3u8支持
if ($file['extension'] == 'm3u8') { if ($file['extension'] == 'm3u8') {
$videoUrl = urlencode("{$file['path']}&cid={$viewData['cacheDataId']}"); $videoUrl = urlencode("{$file['path']}");
}else { }else {
$videoUrl = urlencode($file['path']); $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') { if ($viewData['showType'] == 'video') {
$linkUrl .= "&page={$viewData['page']}&limit={$viewData['pageSize']}"; $linkUrl .= "&page={$viewData['page']}&limit={$viewData['pageSize']}";
} }

Loading…
Cancel
Save