想在文章中插入视频,尝试 iframe 和 video 标签后发现 m3u8 流会触发下载无法播放,用 hls 该问题后,碰到了 403 forbbiden。联想到前些天新浪图床加 referrer 的解决方法,随手一试竟然可以。后来发现 Mixed Content 和 CORS 才是大坑,几经了解,这个问题只能靠视频源服务器解决,所以把视频放在自己的服务器或 CDN 是不会有问题的。最后,用 js 封装了一下神器 DPlayer,使用体验良好。

演示效果

{dplayer src=“https://youku.cdn2-youku.com/20180410/9985_3bdd7f1e/index.m3u8”/}

引入 JS

对于 本主题,依次进入 控制台 - 外观 - 设置外观 - 主题自定义扩展,将代码加入到 自定义 HTML 元素拓展 - 标签: head 头部 (meta 元素后)。其他主题,加入到主题对应的 header.php 中的 标签前。

    <script>
// DPlayer API
document.addEventListener('DOMContentLoaded', initDplayer);
function initDplayer() {
const common = {
loadResource: function (id, resource, type, callback) {
let loaded = document.head.querySelector('#' + id);
if (loaded) {
callback();
return;
}
const element = document.createElement(type);
element.onload = element.onreadystatechange = () => {
if (!loaded && (!element.readyState || /loaded|complete/.test(element.readyState))) {
element.onload = element.onreadystatechange = null;
loaded = true;
callback();
}
}
if (type === 'link') {
element.rel = 'stylesheet';
element.href = resource;
} else {
element.src = resource;
}
element.id = id;
document.getElementsByTagName('head')[0].appendChild(element);
},
loadResources: function (callback) {
const cdn = '//s0.pstatp.com/cdn/expire-1-M';
const resources = [
'/dplayer/1.25.0/DPlayer.min.css',
'/dplayer/1.25.0/DPlayer.min.js',
'/hls.js/0.12.4/hls.light.min.js',
'/flv.js/1.5.0/flv.min.js'
];
let unloadedResourceCount = resources.length;
resources.forEach(resource => {
this.loadResource(btoa(resource).replace(/[=+\/]/g, ''), cdn + resource,
({
'css': 'link',
'js': 'script'
})[resource.split('.').pop()],
() => --unloadedResourceCount ? null : callback()
);
});
},
createDplayers: function (sources, callback) {
for (let i = 0; i < sources.length; i++) {
const child = document.createElement('div');
const src = sources[i].getAttribute('src');
sources[i].parentNode.insertBefore(child, sources[i]);
sources[i].style.display = 'none';
const type = src.split('.').pop();
const option = { url: src };
type === 'flv' ? option.type = type : null;
const dplayer = new DPlayer({ container: child, preload: 'none', autoplay: false, screenshot: false, video: option });
}
if (typeof callback === 'function') callback();
}
};
const mirages = {
isMirages: function () { return Mirages || false },
fixVideoSize: function (length) {
let outerTimer = false;
const outerInterval = setInterval(() => {
if (outerTimer) return;
const videos = document.getElementsByTagName('video');
if (videos.length === length) {
const dplayerWraps = document.querySelectorAll('.dplayer-video-wrap');
for (let i = 0; i < length; i++) {
const videoContainers = dplayerWraps[i].querySelectorAll('.video-container.video-4-3');
if (videoContainers.length) {
videoContainers[0].style = 'position: initial;';
videoContainers[0].className = 'video-container video-16-9';
console.log('video-4-3 fixed.');
} else {
const videoContainer = document.createElement('div');
videoContainer.style = 'position: initial;';
videoContainer.className = 'video-container video-16-9';
videoContainer.appendChild(videos[i]);
dplayerWraps[i].appendChild(videoContainer);
console.log('video-16-9 inserted.');
const targetNode = videoContainer;
const config = { childList: true };
const callback = (mutationsList, observer) => {
const newVideoContainers = videoContainer.querySelectorAll(
'.video-container.video-4-3');
if (newVideoContainers.length) {
newVideoContainers[0].className = '';
console.log('auto inserted video-4-3 fixed.');
observer.disconnect();
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
setTimeout(() => observer.disconnect(), 1000 * 120);
}
}
outerTimer = true;
clearInterval(outerInterval);
}
}, 500);
}
};
const dps = document.getElementsByTagName('dp');
if (dps.length !== 0) {
common.loadResources(() => common.createDplayers(dps, () => {
// 修正 Mirages 视频比例错误
mirages.isMirages() ? mirages.fixVideoSize(dps.length) : null;
}));
}
};
</script>

如果你开启了 PJAX,可能需要单独加入回调函数。对于本主题,依次进入 控制台 - 外观 - 设置外观 - PJAX(BETA) - PJAX RELOAD,将 initDplayer(); 添加进入即可。

添加播放器

在文章所需位置以 html 形式插入代码,即可添加播放器,支持 m3u8、mp4,flv 和 mkv 格式,不过编码必须是 H.264 AAC。

Typecho 引入 DPlayer的更多相关文章

  1. 基于Typecho CMS框架开发大中型应用

    基于Typecho CMS框架开发大中型应用 大中型应用暂且定义为:大于等于3个数据表的应用!汗吧! Typecho原本是一款博客系统,其框架体系有别于市面上一般意义MVC框架,主体代码以自创的Wid ...

  2. 谈谈DOMContentLoaded:Javascript中的domReady引入机制

    一.扯淡部分 回想当年,在摆脱写页面时js全靠从各种DEMO中copy出来然后东拼西凑的幽暗岁月之后,毅然决然地打算放弃这种处处“拿来主义”的不正之风,然后开启通往高大上的“前端攻城狮”的飞升之旅.想 ...

  3. NGINX引入线程池 性能提升9倍

    1. 引言 正如我们所知,NGINX采用了异步.事件驱动的方法来处理连接.这种处理方式无需(像使用传统架构的服务器一样)为每个请求创建额外的专用进程或者线程,而是在一个工作进程中处理多个连接和请求.为 ...

  4. Electron中Jquery的引入方式

    原文链接http://huisky.com/blog/16122220522957 Electron默认启用了Node.js的require模块,而jQuery等新版本框架为了支持commondJS标 ...

  5. iOS引入JavaScriptCore引擎框架(二)

    为何放弃第一种方案 UIWebView的JSContext获取     上篇中,我们通过简单的kvc获取UIWebVIew的JSContext,但是实际上,apple并未给开发者提供访问UIWebVi ...

  6. iOS引入JavaScriptCore引擎框架(一)

    JavaScriptCore引擎     我们都知道WebKit是个渲染引擎,简单来说负责页面的布局,绘制以及层的合成,但是WebKit工程中不仅仅有关于渲染相关的逻辑,也集成了默认的javascri ...

  7. C++01.类的引入

    1.假设我们要输出张三,李四两个人的基本信息,包括姓名,年龄,可以用以下的C程序实现: eg: #include <stdio.h> int main(int argc,char **ar ...

  8. Highchart插件简介和引入方式

    一.Highchart简介: Highcharts 是一个用纯 JavaScript 编写的一个图表库, 能够很简单便捷的在 Web 网站或是 Web 应用程序添加有交互性的图表. Highchart ...

  9. 当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式。

    当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式.比如 select * from T_Employee where FNumber not in ( select top 5*  ...

  10. JavaScript模板引擎artTemplate.js——引入子模板

    之前的例子都是单一结构的对象,如果遇到复杂对象结构,我们可以通过引入子模板来实现html的渲染. 依旧以之前的数据作为例子: <div id="content">< ...

随机推荐

  1. arbitrum 资产桥合约

    资产桥的作用 Rollup 的主要流程中,实际上不包含资产桥,也就是说即使没有资产桥,L2依然能正常运行但是此时L1与L2在数据上是完全独立的两条链,L1不理解L2上的数据(L1只保存L2压缩后的数据 ...

  2. Tableau 数值 以万显示

    # Tableau 数字以万显示 0"."0,万

  3. RepeatReadRequestWrapper

    package cn.service.web.common.filter; import com.alibaba.fastjson.JSON; import org.apache.commons.io ...

  4. Qt编写的视频播放综合应用示例(qmedia/ffmpeg/vlc/mpv/海康sdk等)

    一.功能特点 1.1 基础功能 支持各种音频视频文件格式,比如mp3.wav.mp4.asf.rm.rmvb.mkv等. 支持本地摄像头设备,可指定分辨率.帧率. 支持各种视频流格式,比如rtp.rt ...

  5. Qt音视频开发47-通用视频控件

    一.前言 自从视频监控系统的内核不断增加,从最初的vlc到ffmpeg然后到mpv,后面还陆续增加了海康sdk等,每次增加一个内核,整个视频监控系统就有三五个代码文件需要修改,而且大部分是重复的代码, ...

  6. vue3项目中报错:Unexpected mutation of "xxx" prop

    vue3 中element 弹窗绑定需要通过v-model,这个时候父级会传个dialogVisible(boolean值)过来,结果会报eslint的错. Unexpected mutation o ...

  7. 《Spring Boot+Vue全栈开发实战-王松2018》一书pdf+源码下载

    下载地址为: 链接:https://pan.baidu.com/s/18lnF2KemQTqkKaCRmMbvXA 提取码:1pie 版权声明:本书版权属于出版社和作者.仅学习使用,请于下载后24小时 ...

  8. 一套十万级TPS的IM综合消息系统的架构实践与思考

    本文由作者jhon_11分享,有大量修订和改动. 1.引言 如何设计一款高性能.高并发.高可用的im综合消息平台是很多公司发展过程中会碰到且必须要解决的问题.比如一家公司内部的通讯系统.各个互联网平台 ...

  9. [LC793]阶乘函数后 K 个零

    题目描述 f(x) 是 x! 末尾是 0 的数量.(回想一下 x! = 1 * 2 * 3 * ... * x,且 0! = 1 ) 例如, f(3) = 0 ,因为 3! = 6 的末尾没有 0 : ...

  10. 函数 | Go语言

    函数 不支持命名参数与默认值 可变参数 求多个int的和 func IntSum(x ...int) { sum := 0 for _, v := range x { sum += v } retur ...