Browse Source

video meta get support

master
filesite 4 months ago
parent
commit
cbbc50b6aa
  1. 19
      plugins/Common.php
  2. 56
      themes/beauty/controller/SiteController.php
  3. 12
      themes/beauty/views/site/index.php
  4. 7
      themes/beauty/views/site/player.php
  5. 4
      www/css/beauty.css
  6. 102
      www/js/beauty.js

19
plugins/Common.php

@ -530,7 +530,7 @@ Class Common {
//保存数据到文件缓存 //保存数据到文件缓存
//缓存数据格式:{ctime: timestamp, data: anything} //缓存数据格式:{ctime: timestamp, data: anything}
public static function saveCacheToFile($key, $data) { public static function saveCacheToFile($key, $data, $cacheSubDir = '') {
$cacheData = array( $cacheData = array(
"ctime" => time(), "ctime" => time(),
"data" => $data, "data" => $data,
@ -538,6 +538,11 @@ Class Common {
$jsonData = json_encode($cacheData, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $jsonData = json_encode($cacheData, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$cacheDir = __DIR__ . '/../runtime/cache/'; $cacheDir = __DIR__ . '/../runtime/cache/';
//子目录支持
if (!empty($cacheSubDir)) {
$cacheDir .= preg_match('/\/$/', $cacheSubDir) ? $cacheSubDir : "{$cacheSubDir}/";
}
if (!is_dir($cacheDir)) { if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0700, true); mkdir($cacheDir, 0700, true);
} }
@ -548,8 +553,12 @@ Class Common {
//从文件缓存读取数据 //从文件缓存读取数据
//expireSeconds: 缓存失效时间,默认10分钟 //expireSeconds: 缓存失效时间,默认10分钟
public static function getCacheFromFile($key, $expireSeconds = 600) { public static function getCacheFromFile($key, $expireSeconds = 600, $cacheSubDir = '') {
$cacheDir = __DIR__ . '/../runtime/cache/'; $cacheDir = __DIR__ . '/../runtime/cache/';
//子目录支持
if (!empty($cacheSubDir)) {
$cacheDir .= preg_match('/\/$/', $cacheSubDir) ? $cacheSubDir : "{$cacheSubDir}/";
}
$cache_filename = "{$cacheDir}{$key}.json"; $cache_filename = "{$cacheDir}{$key}.json";
if (file_exists($cache_filename)) { if (file_exists($cache_filename)) {
@ -569,8 +578,12 @@ Class Common {
} }
//删除缓存文件 //删除缓存文件
public static function cleanFileCache($key) { public static function cleanFileCache($key, $cacheSubDir = '') {
$cacheDir = __DIR__ . '/../runtime/cache/'; $cacheDir = __DIR__ . '/../runtime/cache/';
//子目录支持
if (!empty($cacheSubDir)) {
$cacheDir .= preg_match('/\/$/', $cacheSubDir) ? $cacheSubDir : "{$cacheSubDir}/";
}
$cache_filename = "{$cacheDir}{$key}.json"; $cache_filename = "{$cacheDir}{$key}.json";
if (file_exists($cache_filename)) { if (file_exists($cache_filename)) {

56
themes/beauty/controller/SiteController.php

@ -208,8 +208,9 @@ Class SiteController extends Controller {
public function actionPlayer() { public function actionPlayer() {
$videoUrl = $this->get('url', ''); $videoUrl = $this->get('url', '');
if (empty($videoUrl)) { $videoId = $this->get('id', '');
throw new Exception("缺少视频地址url参数!", 403); if (empty($videoUrl) || empty($videoId)) {
throw new Exception("缺少视频地址url或id参数!", 403);
} }
$arr = parse_url($videoUrl); $arr = parse_url($videoUrl);
@ -231,9 +232,58 @@ Class SiteController extends Controller {
$this->layout = 'player'; $this->layout = 'player';
$viewName = 'player'; $viewName = 'player';
$params = compact( $params = compact(
'videoUrl', 'videoFilename', 'copyright' 'videoUrl', 'videoId', 'videoFilename', 'copyright'
); );
return $this->render($viewName, $params, $pageTitle); return $this->render($viewName, $params, $pageTitle);
} }
//根据视频文件id返回缓存数据:
//{duration: 单位秒的时长, snapshot: base64格式的jpg封面图}
public function actionVideometa() {
$code = 1;
$msg = 'OK';
$meta = array();
$videoId = $this->get('id', '');
if (empty($videoId)) {
$code = 0;
$msg = '参数不能为空';
}else {
$cacheKey = $videoId;
$expireSeconds = 86400*30; //有效期30天
$cacheSubDir = 'video';
$cachedData = Common::getCacheFromFile($cacheKey, $expireSeconds, $cacheSubDir);
if (!empty($cachedData)) {
$meta = $cachedData;
}else {
$code = 0;
$msg = '此视频无缓存或缓存已过期';
}
}
return $this->renderJson(compact('code', 'msg', 'meta'));
}
//保存视频meta数据到缓存
public function actionSavevideometa() {
$code = 0;
$msg = 'OK';
$videoId = $this->post('id', '');
$metaData = $this->post('meta', '');
if (empty($videoId) || empty($metaData)) {
$code = 0;
$msg = '参数不能为空';
}else {
$cacheKey = $videoId;
$cacheSubDir = 'video';
$saved = Common::saveCacheToFile($cacheKey, $metaData, $cacheSubDir);
if ($saved !== false) {
$code = 1;
}
}
return $this->renderJson(compact('code', 'msg'));
}
} }

12
themes/beauty/views/site/index.php

@ -258,13 +258,15 @@ eof;
$videoUrl = urlencode($file['path']); $videoUrl = urlencode($file['path']);
echo <<<eof echo <<<eof
<div class="im_item bor_radius col-xs-6 col-sm-4 col-md-3 col-lg-2"> <div class="im_item bor_radius col-xs-6 col-sm-4 col-md-3 col-lg-2">
<a href="/site/player?url={$videoUrl}" target="_blank" class="bor_radius" title="{$title} - {$file['filename']}"> <a href="/site/player?url={$videoUrl}&id={$file['id']}" target="_blank" class="bor_radius" title="{$title} - {$file['filename']}">
<img src="/img/beauty/video_snap.jpg" class="bor_radius im_img" alt="{$file['filename']}"> <img src="/img/beauty/video_snap.jpg" class="bor_radius im_img video-poster" id="poster_{$file['id']}" data-id="{$file['id']}" alt="{$file['filename']}">
<div class="im_img_title"> <div class="im_img_title">
<span class="right-bottom"> <span class="right-bottom">
{$title} {$title}
</span> </span>
</div> </div>
<img src="/img/video-play.svg" class="playbtn" alt="video play button">
<span class="duration">00:00:00</span>
</a> </a>
</div> </div>
eof; eof;
@ -289,13 +291,15 @@ eof;
$videoUrl = urlencode($file['path']); $videoUrl = urlencode($file['path']);
echo <<<eof echo <<<eof
<div class="im_item bor_radius col-xs-6 col-sm-4 col-md-3 col-lg-2"> <div class="im_item bor_radius col-xs-6 col-sm-4 col-md-3 col-lg-2">
<a href="/site/player?url={$videoUrl}" target="_blank" class="bor_radius" title="{$title} - {$file['filename']}"> <a href="/site/player?url={$videoUrl}&id={$file['id']}" target="_blank" class="bor_radius" title="{$title} - {$file['filename']}">
<img src="/img/beauty/video_snap.jpg" class="bor_radius im_img" alt="{$file['filename']}"> <img src="/img/beauty/video_snap.jpg" class="bor_radius im_img video-poster" id="poster_{$file['id']}" data-id="{$file['id']}" alt="{$file['filename']}">
<div class="im_img_title"> <div class="im_img_title">
<span class="right-bottom"> <span class="right-bottom">
{$title} {$title}
</span> </span>
</div> </div>
<img src="/img/video-play.svg" class="playbtn" alt="video play button">
<span class="duration">00:00:00</span>
</a> </a>
</div> </div>
eof; eof;

7
themes/beauty/views/site/player.php

@ -27,12 +27,13 @@
</nav> </nav>
<div class="videoplayer"> <div class="videoplayer">
<video class="video-js vjs-big-play-centered vjs-fluid vjs-16-9" <video
data-id="<?php echo $viewData['videoId']; ?>"
class="video-js vjs-big-play-centered vjs-fluid vjs-16-9"
controls controls
playsinline playsinline
data-setup='{"autoplay":"muted"}'
poster="" poster=""
id="myvideo"> id="my-player">
<source src="<?php echo $viewData['videoUrl']; ?>" type="video/mp4"> <source src="<?php echo $viewData['videoUrl']; ?>" type="video/mp4">
</video> </video>
<div class="text-right mt-2 mr-1"> <div class="text-right mt-2 mr-1">

4
www/css/beauty.css

@ -122,11 +122,13 @@ a:link{text-decoration:none}
.lampshow .text_dark{color:#808080} .lampshow .text_dark{color:#808080}
.lampshow .text_dark a{color:#f4f7fd} .lampshow .text_dark a{color:#f4f7fd}
#qrimg{width:160px;height:160px;margin:0 auto 20px auto;background-color:#FFF;padding:5px;border:1px solid #EEE;border-radius:5px} #qrimg{width:160px;height:160px;margin:0 auto 20px auto;background-color:#FFF;padding:5px;border:1px solid #EEE;border-radius:5px;overflow:hidden}
.videoplayer{max-width:800px;margin:0 auto;text-align:center} .videoplayer{max-width:800px;margin:0 auto;text-align:center}
.videoplayer video{width:100%} .videoplayer video{width:100%}
.videotitle{max-width:600px;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis} .videotitle{max-width:600px;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}
.playbtn{width:50px;height:50px;position:absolute;left:50%;top:50%;margin-top:-25px;margin-left:-25px}
.duration{position:absolute;left:5px;bottom:5px;background-color:#222;padding:0 3px;opacity:0.7;border-radius:3px;font-size:12px;color:#FFF}
.mt-2{margin-top:2em} .mt-2{margin-top:2em}
.mr-1{margin-right:1em} .mr-1{margin-right:1em}

102
www/js/beauty.js

@ -4,6 +4,9 @@
******Tan ******Tan
*/ */
//关闭videojs的ga统计
window.HELP_IMPROVE_VIDEOJS = false;
if ($('#image_site').get(0)) { if ($('#image_site').get(0)) {
// 图片浏览 // 图片浏览
@ -186,3 +189,102 @@ if ($('#qrimg').length > 0 && typeof(QRCode) != 'undefined') {
correctLevel : QRCode.CorrectLevel.L correctLevel : QRCode.CorrectLevel.L
}); });
} }
var formatDuration = function(duration) {
var str = '00:00:00';
var hours = 0, minutes = 0;
if (duration > 3600) {
hours = Math.floor(duration / 3600);
}
if (duration > 60) {
minutes = Math.floor((duration-hours*3600) / 60);
}
var seconds = Math.floor(duration - hours*3600 - minutes*60);
str = hours.toString().padStart(2, '0') + ':'
+ minutes.toString().padStart(2, '0') + ':'
+ seconds.toString().padStart(2, '0');
return str;
};
//视频列表封面图加载
var getVideoMetaAndShowIt = function(videoId) {
$.ajax({
url: '/site/videometa',
method: 'GET',
dataType: 'json',
data: {
id: videoId
}
}).done(function(data) {
if (data.code != 1) {
console.warn('视频数据获取失败', data.msg);
}else {
$('#poster_'+videoId).attr('src', data.meta.snapshot);
$('#poster_'+videoId).parent('a').find('.duration').text(formatDuration(data.meta.duration));
}
}).fail(function(jqXHR, textStatus, errorThrown) {
console.error('视频数据获取失败,错误信息:' + errorThrown);
});
};
$('.video-poster').each(function(index, el) {
var videoId = $(el).attr('data-id');
getVideoMetaAndShowIt(videoId);
});
//保存视频数据
var saveVideoMeta = function(videoId, metaData) {
$.ajax({
url: '/site/savevideometa',
method: 'POST',
dataType: 'json',
data: {
id: videoId,
meta: metaData
}
}).done(function(data) {
if (data.code != 1) {
console.warn('视频数据保存失败', data.msg);
}
}).fail(function(jqXHR, textStatus, errorThrown) {
console.error('视频数据保存失败,错误信息:' + errorThrown);
});
};
//视频播放器
if ($('#my-player').length > 0 && typeof(videojs) != 'undefined') {
var myPlayer = videojs('my-player', {
controls: true,
autoplay: true,
muted: true,
preload: 'auto'
});
myPlayer.one('play', function() {
myPlayer.pause();
var canvas = document.createElement('canvas');
var video = $('video.vjs-tech').get(0);
//360p
canvas.width = 640;
canvas.height = 360;
var ctx = canvas.getContext('2d');
ctx.drawImage( video, 0, 0, canvas.width, canvas.height );
var snapshotImg = canvas.toDataURL('image/jpeg');
saveVideoMeta($('video.vjs-tech').attr('data-id'), {
duration: myPlayer.duration(),
snapshot: snapshotImg
});
myPlayer.play();
});
}
Loading…
Cancel
Save