MENU

Typecho 引入 DPlayer 的简单方法

2019 年 05 月 29 日 • 阅读: 9823 • 博客

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

演示效果

引入 JS

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

JavaScript Code

<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 window.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 形式插入代码,即可添加播放器,支持 m3u8mp4flvmkv 格式,不过编码必须是 H.264 AAC

!!!
<dp src="demo.mp4"></dp>
!!!
TG 大佬群 QQ 大佬群

最后编辑于: 2021 年 06 月 12 日
返回文章列表 文章二维码
本页链接的二维码
打赏二维码
添加新评论

Loading captcha...

已有 18 条评论
  1. zizdog zizdog   Windows 10 x64 Edition  Google Chrome 96.0.4664.55

    直接用插件也挺好的。

  2. 阿斯蒂芬 阿斯蒂芬   Windows 10 x64 Edition  Google Chrome 93.0.4577.82

    我测试一下头像哈

  3. 月下读心 月下读心   Windows 10 x64 Edition  Google Chrome 77.0.3865.120

    怎么引用b站弹幕呢?

    1. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 80.0.3987.132

      @月下读心之前没考虑加弹幕,具体阅读官方文档
      https://dplayer.js.org/zh/guide.html#bilibili-%E5%BC%B9%E5%B9%95

    2. 月下读心 月下读心   Windows 10 x64 Edition  Google Chrome 77.0.3865.120

      @LOGI用了插件,pjax回调出问题了::quyin:hematemesis::
      ![就这](https://i.loli.net/2020/03/15/NbsvAGwgyl3TtPf.png)

    3. 月下读心 月下读心   Windows 10 x64 Edition  Google Chrome 77.0.3865.120

      @月下读心图:https://i.loli.net/2020/03/15/NbsvAGwgyl3TtPf.png

    4. LOGI LOGI   Windows 7 x64 Edition  Google Chrome 80.0.3987.122

      @月下读心放你博客链接,我去看一下

    5. 月下读心 月下读心   Windows 10 x64 Edition  Google Chrome 77.0.3865.120

      @LOGI这 https://nianshaoke.cn/archives/198

    6. LOGI LOGI   Windows 7 x64 Edition  Google Chrome 80.0.3987.122

      @月下读心我过去看挺正常的,或许你可以 ctrl + f5 刷新下

    7. 月下读心 月下读心   Windows 10 x64 Edition  Google Chrome 77.0.3865.120

      @LOGI感谢大佬#(喜极而泣)

  4. 小童 小童   Windows 10 x64 Edition  Google Chrome 79.0.3945.130

    大佬,你说新浪图床加referrer的解决方法是指添加add_header Referrer-Policy "no-referrer";这个吗?
    我试过把这个加进宝塔网站配置文件中,加了没有效果诶@(泪)

    1. LOGI LOGI   Windows 7 x64 Edition  Google Chrome 79.0.3945.130

      @小童是在 head 里面加,不过那样有副作用。现在建议反代,或者最好用自己的 cdn

    2. 童   Windows 10 x64 Edition  QQ 浏览器 10.5.3863.400

      @LOGI想暂时用这个方法恢复那些失效的图片文件然后一个个下载下来.....
      那个大佬的微博图片本地化太复杂了,我不会正则循环什么的只好用这个慢方法了@(泪)

    3. LOGI LOGI   Windows 7 x64 Edition  Google Chrome 79.0.3945.130

      @童那位大佬关键步骤都给了,不过跳过了数据库导出等零散步骤。我有时间再写一篇详细点的吧

    4. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 80.0.3987.106

      @童我写了一篇帖子你看看

      https://logi.im/blog/a-whole-review-of-sinaimg-server-referrer-limitation.html

  5. Xin Xin   Windows 7 x64 Edition  Google Chrome 75.0.3770.100

    本站已启用,谢谢站长耐心指导

  6. Kevan Kevan   Mac OS X 10.14.3  Google Chrome 75.0.3770.100

    很实用了,打算给自己的加上

    1. LOGI LOGI   Windows 10 x64 Edition  Google Chrome 75.0.3770.100

      @Kevan感谢支持,交换一下友链吧@(太开心)