Merge branch 'master' into for-pr

This commit is contained in:
DIYgod 2022-08-15 20:04:30 +01:00 committed by GitHub
commit 414a035cef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 13097 additions and 9850 deletions

View File

@ -9,8 +9,6 @@
[![npm](https://img.shields.io/npm/l/dplayer.svg?style=flat-square)](https://github.com/MoePlayer/DPlayer/blob/master/LICENSE)
[![npm](https://img.shields.io/npm/dt/dplayer.svg?style=flat-square)](https://www.npmjs.com/package/dplayer)
[![size](https://badge-size.herokuapp.com/MoePlayer/DPlayer/master/dist/DPlayer.min.js?compression=gzip&style=flat-square)](https://github.com/MoePlayer/DPlayer/tree/master/dist)
[![Travis](https://img.shields.io/travis/MoePlayer/DPlayer.svg?style=flat-square)](https://travis-ci.org/MoePlayer/DPlayer)
[![devDependency Status](https://img.shields.io/david/dev/MoePlayer/dplayer.svg?style=flat-square)](https://david-dm.org/MoePlayer/DPlayer#info=devDependencies)
## Introduction
@ -46,13 +44,7 @@ Using DPlayer on your project? [Let me know!](https://github.com/DIYgod/DPlayer/
## Thanks
### Special Sponsors
<div>
<a href="https://www.cdnbye.com" target="_blank">
<img height="60px" src="https://cdnbye.oss-cn-beijing.aliyuncs.com/pic/cdnbye-dp.jpeg">
</a>
</div>
### Sponsors
<div>
<a href="https://www.dogecloud.com/?ref=dplayer" target="_blank">
@ -60,20 +52,10 @@ Using DPlayer on your project? [Let me know!](https://github.com/DIYgod/DPlayer/
</a>
</div>
### Sponsors
| [极酷社](https://www.acg.app) |
| :---------------------------: |
### Contributors
<a href="https://github.com/MoePlayer/DPlayer/graphs/contributors"><img src="https://opencollective.com/DPlayer/contributors.svg?width=890" /></a>
## Join the Discussion
- [Telegram Group](https://t.me/adplayer)
## Related Projects
Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/DPlayer/issues/31)
@ -104,7 +86,8 @@ Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/DPlay
### Other
- [DPlayer-Lite](https://github.com/kn007/DPlayer-Lite): lite version
- [hlsjs-p2p-engine](https://github.com/cdnbye/hlsjs-p2p-engine)
- [hlsjs-p2p-engine](https://github.com/cdnbye/hlsjs-p2p-engine): Let your viewers become your unlimitedly scalable CDN
- [CBPlayer](https://github.com/cdnbye/CBPlayer): Dplayer with CDNBye P2P plugin built in, supporting HLS, MP4 and MPEG-DASH P2P streaming.
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/DPlayer/issues/31)
## Who use DPlayer?
@ -119,26 +102,32 @@ Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/DPlay
- [otomads](https://otomads.com/): 专注于音 MAD 的视频弹幕网站
- [Cloudreve](https://github.com/HFO4/Cloudreve): 基于 ThinkPHP 构建的网盘系统
- [oneindex](https://github.com/donwa/oneindex): Onedrive Directory Index
- [arozos](https://github.com/tobychui/arozos): General purposed Web Desktop Operating Platform / OS for Raspberry Pis
- [新东方云教室](https://roombox.xdf.cn/)
- [BBHouse](https://github.com/endcloud/bbhouse-tauri): A Bilibili Cross-Platform Desktop Client Powered By Tauri
- [Tampermonkey 阿里云盘](https://greasyfork.org/zh-CN/scripts/425955-%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98)
- Feel free to submit yours in [`Let me know!`](https://github.com/MoePlayer/DPlayer/issues/31)
## Donate
DPlayer is an MIT licensed open source project and completely free to use. However, the amount of effort needed to maintain and develop new features for the project is not sustainable without proper financial backing.
## One-time Donations
You can support DPlayer via donations.
We accept donations through these channels:
### Recurring Donation
- Become a Sponser on [GitHub](https://github.com/sponsors/DIYgod)
- Become a Sponser on [Patreon](https://www.patreon.com/DIYgod)
- Become a Sponser on [爱发电](https://afdian.net/@diygod)
- Contact us directly: i@diygod.me
### One-time Donation
We accept donations via the following ways:
- [WeChat Pay](https://diygod.me/images/wx.jpg)
- [Alipay](https://diygod.me/images/zfb.jpg)
- [Paypal](https://www.paypal.me/DIYgod)
- [WeChat Pay](https://i.imgur.com/aq6PtWa.png)
- [Alipay](https://i.imgur.com/wv1Pj2k.png)
## Recurring Pledges
Recurring pledges come with exclusive perks, e.g. enabling faster GitHub response, having your name or your company logo listed in the DPlayer GitHub repository and this website.
- Become a backer or sponsor via [Patreon](https://www.patreon.com/DIYgod)
- E-mail us: i#html.love
## Author

View File

@ -83,6 +83,7 @@ function initPlayers() {
loop: true,
screenshot: true,
airplay: true,
chromecast: true,
hotkey: true,
logo: 'https://i.loli.net/2019/06/06/5cf8c5d94521136430.png',
volume: 0.2,
@ -103,11 +104,13 @@ function initPlayers() {
danmaku: {
id: '9E2E3368B56CDBB4',
api: 'https://api.prprpr.me/dplayer/',
addition: ['https://s-sh-17-dplayercdn.oss.dogecdn.com/1678963.json'],
token: 'tokendemo',
maximum: 3000,
user: 'DIYgod',
bottom: '15%',
unlimited: true
unlimited: true,
speedRate: 0.5,
},
contextmenu: [
{

2
dist/DPlayer.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -38,6 +38,7 @@ module.exports = {
['script', { src: 'https://cdn.jsdelivr.net/webtorrent/latest/webtorrent.min.js' }],
['script', { src: 'https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js' }],
],
theme: 'vuepress-theme-dplayer',
themeConfig: {
repo: 'MoePlayer/DPlayer',
editLinks: true,

View File

@ -0,0 +1,65 @@
<script>
export default {
name: 'CarbonAds',
watch: {
'$route' (to, from) {
if (
to.path !== from.path
// Only reload if the ad has been loaded
// otherwise it's possible that the script is appended but
// the ads are not loaded yet. This would result in duplicated ads.
&& this.$el.querySelector('#carbonads')
) {
this.$el.innerHTML = ''
this.load()
}
}
},
mounted () {
this.load()
},
methods: {
load () {
const s = document.createElement('script')
s.id = '_carbonads_js'
s.src = `//cdn.carbonads.com/carbon.js?serve=CEAI6277&placement=dplayerjsorg`
this.$el.appendChild(s)
}
},
render (h) {
return h('div', { class: 'carbon-ads' })
}
}
</script>
<style lang="stylus">
.carbon-ads
min-height 102px
padding 1.5rem 1.5rem 0
margin-bottom -0.5rem
font-size 0.75rem
a
color #444
font-weight normal
display inline
.carbon-img
float left
margin-right 1rem
border 1px solid $borderColor
img
display block
.carbon-poweredby
color #999
display block
margin-top 0.5em
@media (max-width: $MQMobile)
.carbon-ads
.carbon-img img
width 100px
height 77px
</style>

View File

@ -0,0 +1,3 @@
module.exports = {
extend: '@vuepress/theme-default',
};

View File

@ -0,0 +1,21 @@
<template>
<ParentLayout>
<template #sidebar-top>
<CarbonAds />
</template>
</ParentLayout>
</template>
<script>
import ParentLayout from '@parent-theme/layouts/Layout.vue'
import CarbonAds from '@theme/components/CarbonAds.vue'
export default {
name: 'Layout',
components: {
ParentLayout,
CarbonAds,
}
}
</script>

View File

@ -0,0 +1,4 @@
{
"name": "vuepress-theme-dplayer",
"main": "index.js"
}

View File

@ -8,10 +8,6 @@ Let's make DPlayer better, feel free to submit yours in [`Let me know!`](https:/
## Help
### Joining the Discussion
- [Telegram Group](https://t.me/adplayer)
### Creating issue
- [MoePlayer/DPlayer/issues](https://github.com/MoePlayer/DPlayer/issues)
@ -57,6 +53,10 @@ Let's make DPlayer better, feel free to submit yours in [`Let me know!`](https:/
- [纸飞机南航青年网络社区](http://my.nuaa.edu.cn/video-video.html): 南京航空航天大学门户网站
- [otomads](https://otomads.com/): 专注于音 MAD 的视频弹幕网站
- [Cloudreve](https://github.com/HFO4/Cloudreve): 基于 ThinkPHP 构建的网盘系统
- [arozos](https://github.com/tobychui/arozos): General purposed Web Desktop Operating Platform / OS for Raspberry Pis
- [新东方云教室](https://roombox.xdf.cn/)
- [BBHouse](https://github.com/endcloud/bbhouse-tauri): A Bilibili Cross-Platform Desktop Client Powered By Tauri
- [Tampermonkey 阿里云盘](https://greasyfork.org/zh-CN/scripts/425955-%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98)
## Contributors

View File

@ -14,28 +14,16 @@ sidebar: auto
## Special Thanks
### Special Sponsors
### Sponsors
&nbsp;
<div>
<a href="https://www.cdnbye.com" target="_blank">
<img height="60px" src="https://cdnbye.oss-cn-beijing.aliyuncs.com/pic/cdnbye-dp.jpeg">
</a>
</div>
<div>
<a href="https://www.dogecloud.com/?ref=dplayer" target="_blank">
<img height="60px" src="https://i.imgur.com/C2NgugY.png">
</a>
</div>
### Sponsors
| [极酷社](https://www.acg.app) |
| :---------------------------: |
## Installation
Using npm:
@ -103,7 +91,8 @@ You can custom your player instance by those options
| loop | false | video loop |
| lang | navigator.language.toLowerCase() | values: 'en', 'zh-cn', 'zh-tw' |
| screenshot | false | enable screenshot, if true, video and video poster must enable Cross-Origin |
| airplay | true | enable airplay in Safari |
| airplay | false | enable airplay in Safari |
| chromecast | false | enable Chromecast |
| hotkey | true | enable hotkey, support FF, FR, volume control, play & pause |
| preload | 'auto' | values: 'none', 'metadata', 'auto' |
| volume | 0.7 | default volume, notice that player will remember user setting, default volume will not work after user set volume themselves |
@ -133,6 +122,7 @@ You can custom your player instance by those options
| danmaku.user | 'DIYgod' | danmaku user name |
| danmaku.bottom | - | values like: '10px' '10%', the distance between the danmaku bottom and player bottom, in order to prevent warding off subtitle |
| danmaku.unlimited | false | display all danmaku even though danmaku overlap, notice that player will remember user setting, default setting will not work after user set it themselves |
| danmaku.speedRate | 1 | danmaku speed multiplier, the larger the faster |
| contextmenu | [] | custom contextmenu |
| highlight | [] | custom time markers upon progress bar |
| mutex | true | prevent to play multiple player at the same time, pause other players when this player start play |
@ -172,6 +162,7 @@ const dp = new DPlayer({
user: 'DIYgod',
bottom: '15%',
unlimited: true,
speedRate: 0.5,
},
contextmenu: [
{
@ -703,22 +694,32 @@ DPlayer can work with any MSE library via `customType` option.
```html
<div id="dplayer"></div>
<script src="pearplayer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cdnbye@latest"></script>
<script src="DPlayer.min.js"></script>
```
```js
var type = 'normal';
if (Hls.isSupported() && Hls.WEBRTC_SUPPORT) {
type = 'customHls';
}
const dp = new DPlayer({
container: document.getElementById('dplayer'),
video: {
url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4',
type: 'pearplayer',
url: 'demo.m3u8',
type: type,
customType: {
pearplayer: function (video, player) {
new PearPlayer(video, {
src: video.src,
autoplay: player.options.autoplay,
customHls: function (video, player) {
const hls = new Hls({
debug: false,
// Other hlsjsConfig options provided by hls.js
p2pConfig: {
live: false,
// Other p2pConfig options provided by CDNBye http://www.cdnbye.com/en/
},
});
hls.loadSource(video.src);
hls.attachMedia(video);
},
},
},
@ -747,11 +748,11 @@ const dp = new DPlayer({
apiBackend: {
read: function (options) {
console.log('Pretend to connect WebSocket');
callback();
options.success([]);
},
send: function (options) {
console.log('Pretend to send danmaku via WebSocket', options.data);
callback();
options.success();
},
},
video: {

View File

@ -10,44 +10,30 @@ If you run a business and are using DPlayer in a revenue-generating product, it
If you are an individual user and have enjoyed the productivity of using DPlayer, consider donating as a sign of appreciation - like buying me coffee once in a while :)
You can support DPlayer development via the following methods:
You can support DPlayer via donations.
## One-time Donations
### Recurring Donation
We accept donations through these channels:
Recurring donors will be rewarded via express issue response, or even have your name displayed on our GitHub page and website.
- Become a Sponser on [GitHub](https://github.com/sponsors/DIYgod)
- Become a Sponser on [Patreon](https://www.patreon.com/DIYgod)
- Become a Sponser on [爱发电](https://afdian.net/@diygod)
- Contact us directly: i@diygod.me
### One-time Donation
We accept donations via the following ways:
- [WeChat Pay](https://diygod.me/images/wx.jpg)
- [Alipay](https://diygod.me/images/zfb.jpg)
- [Paypal](https://www.paypal.me/DIYgod)
- [WeChat Pay](https://i.imgur.com/aq6PtWa.png)
- [Alipay](https://i.imgur.com/wv1Pj2k.png)
## Recurring Pledges
## Sponsors
Recurring pledges come with exclusive perks, e.g. having your name or your company logo listed in the DPlayer GitHub repository and this website.
- Become a Backer or a Sponser on [Patreon](https://www.patreon.com/DIYgod)
- E-mail us: i#diygod.me
## Current Premium Sponsors
### Special Sponsors
<div>
<a href="https://www.cdnbye.com" target="_blank">
<img height="60px" src="https://cdnbye.oss-cn-beijing.aliyuncs.com/pic/cdnbye-dp.jpeg">
</a>
</div>
<div>
<a href="https://www.dogecloud.com/?ref=dplayer" target="_blank">
<img height="60px" src="https://i.imgur.com/C2NgugY.png">
<img width="222px" src="https://i.imgur.com/BBKXPAp.png">
</a>
</div>
### Sponsors
| [极酷社](https://www.acg.app) |
| :---------------------------: |
## DPlayer contributors

View File

@ -8,10 +8,6 @@ sidebar: auto
## 帮助
### 参与讨论
- [Telegram 群](https://t.me/adplayer)
### 提交 issue
- [MoePlayer/DPlayer/issues](https://github.com/MoePlayer/DPlayer/issues)
@ -57,3 +53,7 @@ sidebar: auto
- [纸飞机南航青年网络社区](http://my.nuaa.edu.cn/video-video.html): 南京航空航天大学门户网站
- [otomads](https://otomads.com/): 专注于音 MAD 的视频弹幕网站
- [Cloudreve](https://github.com/HFO4/Cloudreve): 基于 ThinkPHP 构建的网盘系统
- [arozos](https://github.com/tobychui/arozos): General purposed Web Desktop Operating Platform / OS for Raspberry Pis
- [新东方云教室](https://roombox.xdf.cn/)
- [BBHouse](https://github.com/endcloud/bbhouse-tauri): A Bilibili Cross-Platform Desktop Client Powered By Tauri
- [Tampermonkey 阿里云盘](https://greasyfork.org/zh-CN/scripts/425955-%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98)

View File

@ -14,13 +14,7 @@ sidebar: auto
## Special Thanks
### Special Sponsors
<div>
<a href="https://www.cdnbye.com" target="_blank">
<img height="60px" src="https://cdnbye.oss-cn-beijing.aliyuncs.com/pic/cdnbye-dp.jpeg">
</a>
</div>
### Sponsors
<div>
<a href="https://www.dogecloud.com/?ref=dplayer" target="_blank">
@ -28,12 +22,6 @@ sidebar: auto
</a>
</div>
### Sponsors
| [极酷社](https://www.acg.app) |
| :---------------------------: |
## 安装
使用 npm:
@ -94,7 +82,8 @@ DPlayer 有丰富的参数可以自定义你的播放器实例
| lang | navigator.language.toLowerCase() | 可选值: 'en', 'zh-cn', 'zh-tw' |
| screenshot | false | 开启截图,如果开启,视频和视频封面需要允许跨域 |
| hotkey | true | 开启热键,支持快进、快退、音量控制、播放暂停 |
| airplay | true | 在 Safari 中开启 AirPlay |
| airplay | false | 在 Safari 中开启 AirPlay |
| chromecast | false | 启用 Chromecast |
| preload | 'auto' | 视频预加载,可选值: 'none', 'metadata', 'auto' |
| volume | 0.7 | 默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 |
| playbackSpeed | [0.5, 0.75, 1, 1.25, 1.5, 2] | 可选的播放速率,可以设置成自定义的数组 |
@ -123,6 +112,7 @@ DPlayer 有丰富的参数可以自定义你的播放器实例
| danmaku.user | 'DIYgod' | 弹幕用户名 |
| danmaku.bottom | - | 弹幕距离播放器底部的距离,防止遮挡字幕,取值形如: '10px' '10%' |
| danmaku.unlimited | false | 海量弹幕模式,即使重叠也展示全部弹幕,请注意播放器会记忆用户设置,用户手动设置后即失效 |
| danmaku.speedRate | 1 | 弹幕速度倍率,越大速度越快 |
| contextmenu | [] | 自定义右键菜单 |
| highlight | [] | 自定义进度条提示点 |
| mutex | true | 互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器 |
@ -162,6 +152,7 @@ const dp = new DPlayer({
user: 'DIYgod',
bottom: '15%',
unlimited: true,
speedRate: 0.5,
},
contextmenu: [
{
@ -683,26 +674,36 @@ const dp = new DPlayer({
### 配合其他 MSE 库使用
DPlayer 可以通过 `customType` 参数与任何 MSE 库一起使用
DPlayer 可以通过 `customType` 参数与任何 MSE 库一起使用,例如支持 P2P 插件:
```html
<div id="dplayer"></div>
<script src="pearplayer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cdnbye@latest"></script>
<script src="DPlayer.min.js"></script>
```
```js
var type = 'normal';
if (Hls.isSupported() && Hls.WEBRTC_SUPPORT) {
type = 'customHls';
}
const dp = new DPlayer({
container: document.getElementById('dplayer'),
video: {
url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4',
type: 'pearplayer',
url: 'demo.m3u8',
type: type,
customType: {
pearplayer: function (video, player) {
new PearPlayer(video, {
src: video.src,
autoplay: player.options.autoplay,
customHls: function (video, player) {
const hls = new Hls({
debug: false,
// Other hlsjsConfig options provided by hls.js
p2pConfig: {
live: false, // 如果是直播设为true
// Other p2pConfig options provided by CDNBye http://www.cdnbye.com/cn/
},
});
hls.loadSource(video.src);
hls.attachMedia(video);
},
},
},
@ -729,13 +730,13 @@ const dp = new DPlayer({
live: true,
danmaku: true,
apiBackend: {
read: function (endpoint, callback) {
read: function (options) {
console.log('Pretend to connect WebSocket');
callback();
options.success([]);
},
send: function (endpoint, danmakuData, callback) {
console.log('Pretend to send danmaku via WebSocket', danmakuData);
callback();
send: function (options) {
console.log('Pretend to send danmaku via WebSocket', options.data);
options.success();
},
},
video: {

View File

@ -10,32 +10,24 @@ DPlayer 是采用 MIT 许可的开源项目,使用完全免费。 但是随着
如果你是个人开发者并且享受 DPlayer 带来的高开发效率,可以用捐助来表示你的谢意 —— 比如偶尔给我买杯咖啡 :)
你可以通过下列的方法来赞助 DPlayer 的开发。
## 一次性赞助
我们通过以下方式接受赞助:
- [微信支付](https://i.imgur.com/aq6PtWa.png)
- [支付宝](https://i.imgur.com/wv1Pj2k.png)
- [Paypal](https://www.paypal.me/DIYgod)
你可以通过下列的方法来赞助 DPlayer 的开发.
## 周期性赞助
周期性赞助可以获得额外的回报,比如你的名字或你的公司 logo 会出现在 DPlayer 的 GitHub 仓库和现在我们的官网中。
- 通过 [GitHub](https://github.com/sponsors/DIYgod) 赞助
- 通过 [Patreon](https://www.patreon.com/DIYgod) 赞助
- 给我们发邮件联系赞助事宜: i#diygod.me
- 通过 [爱发电](https://afdian.net/@diygod) 赞助
- 给我们发邮件联系赞助事宜: <i@diygod.me>
## 当前的顶级赞助商
## 一次性赞助
### Special Sponsors
我们通过以下方式接受赞助:
<div>
<a href="https://www.cdnbye.com" target="_blank">
<img height="60px" src="https://cdnbye.oss-cn-beijing.aliyuncs.com/pic/cdnbye-dp.jpeg">
</a>
</div>
- [微信支付](https://diygod.me/images/wx.jpg)
- [支付宝](https://diygod.me/images/zfb.jpg)
- [Paypal](https://www.paypal.me/DIYgod)
## 赞助商
<div>
<a href="https://www.dogecloud.com/?ref=dplayer" target="_blank">
@ -43,12 +35,6 @@ DPlayer 是采用 MIT 许可的开源项目,使用完全免费。 但是随着
</a>
</div>
### Sponsors
| [极酷社](https://www.acg.app) |
| :---------------------------: |
## DPlayer 贡献者
感谢所有贡献者。

View File

@ -5,8 +5,8 @@
"main": "dist/DPlayer.min.js",
"scripts": {
"start": "npm run dev",
"build": "cross-env NODE_ENV=production webpack --config webpack/prod.config.js --progress --display-error-details --colors",
"dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack/dev.config.js --watch --colors",
"build": "cross-env NODE_ENV=production webpack --config webpack/prod.config.js --progress",
"dev": "cross-env NODE_ENV=development webpack serve --config webpack/dev.config.js",
"test": "eslint src webpack",
"format": "eslint \"**/*.js\" --fix && prettier \"**/*.{js,json,md}\" --write",
"format:staged": "eslint \"**/*.js\" --fix && pretty-quick --staged --verbose --pattern \"**/*.{js,json,md}\"",
@ -39,44 +39,47 @@
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/preset-env": "^7.4.5",
"@vuepress/plugin-back-to-top": "1.7.1",
"@vuepress/plugin-google-analytics": "1.7.1",
"@vuepress/plugin-pwa": "1.7.1",
"@vuepress/plugin-back-to-top": "1.9.7",
"@vuepress/plugin-google-analytics": "1.9.7",
"@vuepress/plugin-pwa": "1.9.7",
"art-template": "4.13.2",
"art-template-loader": "1.4.3",
"autoprefixer": "^9.6.1",
"autoprefixer": "^10.4.8",
"babel-loader": "^8.0.6",
"cross-env": "^7.0.0",
"css-loader": "^5.0.0",
"cssnano": "^4.1.10",
"eslint": "^7.0.0",
"eslint-config-prettier": "^6.3.0",
"eslint-loader": "^4.0.0",
"eslint-plugin-prettier": "^3.1.1",
"exports-loader": "^1.0.0",
"css-loader": "^6.7.1",
"cssnano": "^5.1.13",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-prettier": "^4.2.1",
"exports-loader": "^4.0.0",
"file-loader": "^6.0.0",
"git-revision-webpack-plugin": "^3.0.3",
"mini-css-extract-plugin": "1.3.0",
"node-sass": "^5.0.0",
"postcss-loader": "^3.0.0",
"git-revision-webpack-plugin": "^5.0.0",
"less": "^4.1.3",
"less-loader": "^11.0.0",
"mini-css-extract-plugin": "2.6.1",
"postcss": "^8.4.16",
"postcss-loader": "^7.0.1",
"postcss-preset-env": "^7.7.2",
"prettier": "^2.0.4",
"prettier-check": "^2.0.0",
"pretty-quick": "^3.0.0",
"sass-loader": "^10.0.0",
"strip-loader": "^0.1.2",
"style-loader": "^2.0.0",
"style-loader": "^3.3.1",
"svg-inline-loader": "0.8.2",
"template-string-optimize-loader": "^3.0.0",
"url-loader": "^4.1.0",
"vuepress": "1.7.1",
"webpack": "^4.40.2",
"webpack-cli": "3.3.12",
"webpack-dev-server": "^3.8.1",
"vuepress": "1.9.7",
"webpack": "^5.74.0",
"webpack-cli": "4.10.0",
"webpack-dev-server": "^4.10.0",
"yorkie": "^2.0.0"
},
"dependencies": {
"axios": "0.21.0",
"axios": "0.27.2",
"balloon-css": "^1.0.3",
"promise-polyfill": "8.2.0"
"promise-polyfill": "8.2.3",
"rxjs": "^7.5.6"
}
}

12648
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="chromecast" class="svg-inline--fa fa-chromecast fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M447.8,64H64c-23.6,0-42.7,19.1-42.7,42.7v63.9H64v-63.9h383.8v298.6H298.6V448H448c23.6,0,42.7-19.1,42.7-42.7V106.7 C490.7,83.1,471.4,64,447.8,64z M21.3,383.6L21.3,383.6l0,63.9h63.9C85.2,412.2,56.6,383.6,21.3,383.6L21.3,383.6z M21.3,298.6V341 c58.9,0,106.6,48.1,106.6,107h42.7C170.7,365.6,103.7,298.7,21.3,298.6z M213.4,448h42.7c-0.5-129.5-105.3-234.3-234.8-234.6l0,42.4 C127.3,255.6,213.3,342,213.4,448z"></path></svg>

After

Width:  |  Height:  |  Size: 642 B

View File

@ -60,11 +60,11 @@
animation: diplayer-loading-dot-fade .8s ease infinite;
opacity: 0;
transform-origin: 4px 4px;
@for $i from 7 through 1 {
&.diplayer-loading-dot-#{$i} {
animation-delay: .1s * $i;
each(range(7), {
&.diplayer-loading-dot-@{value} {
animation-delay: (@value * 0.1s);
}
}
});
}
@keyframes diplayer-loading-dot-fade {
0% {

View File

@ -24,7 +24,8 @@
transform: translateX(100%);
&.dplayer-danmaku-move {
will-change: transform;
animation: danmaku 5s linear;
animation-name: 'danmaku';
animation-timing-function: linear;
animation-play-state: paused;
}
}
@ -41,7 +42,8 @@
visibility: hidden;
&.dplayer-danmaku-move {
will-change: visibility;
animation: danmaku-center 4s linear;
animation-name: 'danmaku-center';
animation-timing-function: linear;
animation-play-state: paused;
}
}

View File

@ -29,23 +29,7 @@
margin: 0;
padding: 0;
transform: translate(0, 0);
.dplayer-danmaku {
.dplayer-danmaku-top,
.dplayer-danmaku-bottom {
&.dplayer-danmaku-move {
animation: danmaku-center 6s linear;
animation-play-state: inherit;
}
}
.dplayer-danmaku-right {
&.dplayer-danmaku-move {
animation: danmaku 8s linear;
animation-play-state: inherit;
}
}
}
}
&.dplayer-no-danmaku {
@ -167,6 +151,7 @@
.dplayer-volume,
.dplayer-camera-icon,
.dplayer-airplay-icon,
.dplayer-chromecast-icon,
.dplayer-play-icon {
display: none;
}

View File

@ -1,6 +1,11 @@
import utils from './utils';
import Thumbnails from './thumbnails';
import Icons from './icons';
import { Subject } from 'rxjs';
let cast;
let runOnce = true;
let isCasting = false;
class Controller {
constructor(player) {
@ -31,6 +36,7 @@ class Controller {
this.initSubtitleButton();
this.initHighlights();
this.initAirplayButton();
this.initChromecastButton();
if (!utils.isMobile) {
this.initVolumeButton();
}
@ -243,9 +249,8 @@ class Controller {
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(dataURL);
this.player.events.trigger('screenshot', dataURL);
});
this.player.events.trigger('screenshot', dataURL);
});
}
}
@ -279,6 +284,90 @@ class Controller {
}
}
initChromecast() {
const script = window.document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1');
window.document.body.appendChild(script);
window.__onGCastApiAvailable = (isAvailable) => {
if (isAvailable) {
cast = window.chrome.cast;
const sessionRequest = new cast.SessionRequest(cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID);
const apiConfig = new cast.ApiConfig(
sessionRequest,
() => {},
(status) => {
if (status === cast.ReceiverAvailability.AVAILABLE) {
console.log('chromecast: ', status);
}
}
);
cast.initialize(apiConfig, () => {});
}
};
}
initChromecastButton() {
if (this.player.options.chromecast) {
if (runOnce) {
runOnce = false;
this.initChromecast();
}
const discoverDevices = () => {
const subj = new Subject();
cast.requestSession(
(s) => {
this.session = s;
subj.next('CONNECTED');
launchMedia(this.player.options.video.url);
},
(err) => {
if (err.code === 'cancel') {
this.session = undefined;
subj.next('CANCEL');
} else {
console.error('Error selecting a cast device', err);
}
}
);
return subj;
};
const launchMedia = (media) => {
const mediaInfo = new cast.media.MediaInfo(media);
const request = new cast.media.LoadRequest(mediaInfo);
if (!this.session) {
window.open(media);
return false;
}
this.session.loadMedia(request, onMediaDiscovered.bind(this, 'loadMedia'), onMediaError).play();
return true;
};
const onMediaDiscovered = (how, media) => {
this.currentMedia = media;
};
const onMediaError = (err) => {
console.error('Error launching media', err);
};
this.player.template.chromecastButton.addEventListener('click', () => {
if (isCasting) {
isCasting = false;
this.currentMedia.stop();
this.session.stop();
this.initChromecast();
} else {
isCasting = true;
discoverDevices();
}
});
}
}
initSubtitleButton() {
if (this.player.options.subtitle) {
this.player.events.on('subtitle_show', () => {

View File

@ -3,6 +3,7 @@ import utils from './utils';
class Danmaku {
constructor(options) {
this.options = options;
this.player = this.options.player;
this.container = this.options.container;
this.danTunnel = {
right: {},
@ -254,6 +255,7 @@ class Danmaku {
if (tunnel >= 0) {
// move
item.classList.add('dplayer-danmaku-move');
item.style.animationDuration = this._danAnimation(dan[i].type);
// insert
docFragment.appendChild(item);
@ -343,6 +345,21 @@ class Danmaku {
unlimit(boolean) {
this.unlimited = boolean;
}
speed(rate) {
this.options.api.speedRate = rate;
}
_danAnimation(position) {
const rate = this.options.api.speedRate || 1;
const isFullScreen = !!this.player.fullScreen.isFullScreen();
const animations = {
top: `${(isFullScreen ? 6 : 4) / rate}s`,
right: `${(isFullScreen ? 8 : 5) / rate}s`,
bottom: `${(isFullScreen ? 6 : 4) / rate}s`,
};
return animations[position];
}
}
export default Danmaku;

View File

@ -53,6 +53,7 @@ const tranTxt = {
Send: '发送',
Screenshot: '截图',
AirPlay: '无线投屏',
ChromeCast: 'ChromeCast',
s: '秒',
'Show subtitle': '显示字幕',
'Hide subtitle': '隐藏字幕',
@ -93,6 +94,7 @@ const tranTxt = {
Send: '發送',
Screenshot: '截圖',
AirPlay: '無線投屏',
ChromeCast: 'ChromeCast',
s: '秒',
'Show subtitle': '顯示字幕',
'Hide subtitle': '隱藏字幕',
@ -100,6 +102,46 @@ const tranTxt = {
Live: '直播',
'Video info': '影片統計訊息',
},
'ko-kr': {
'Danmaku is loading': 'Danmaku를 불러오는 중입니다.',
Top: 'Top',
Bottom: 'Bottom',
Rolling: 'Rolling',
'Input danmaku, hit Enter': 'Danmaku를 입력하고 Enter를 누르세요.',
'About author': '만든이',
'DPlayer feedback': '피드백 보내기',
'About DPlayer': 'DPlayer 정보',
Loop: '반복',
Speed: '배속',
'Opacity for danmaku': 'Danmaku 불투명도',
Normal: '표준',
'Please input danmaku content!': 'Danmaku를 입력하세요!',
'Set danmaku color': 'Danmaku 색상',
'Set danmaku type': 'Danmaku 설정',
'Show danmaku': 'Danmaku 표시',
'Video load failed': '비디오를 불러오지 못했습니다.',
'Danmaku load failed': 'Danmaku를 불러오지 못했습니다.',
'Danmaku send failed': 'Danmaku 전송에 실패했습니다.',
'Switching to': '전환',
'Switched to': '전환 됨',
quality: '화질',
FF: '앞으로',
REW: '뒤로',
'Unlimited danmaku': '끝없는 Danmaku',
'Send danmaku': 'Danmaku 보내기',
Setting: '설정',
'Full screen': '전체 화면',
'Web full screen': '웹 내 전체화면',
Send: '보내기',
Screenshot: '화면 캡쳐',
AirPlay: '에어플레이',
s: '초',
'Show subtitle': '자막 보이기',
'Hide subtitle': '자막 숨기기',
Volume: '볼륨',
Live: '생방송',
'Video info': '비디오 정보',
},
};
export default i18n;

View File

@ -15,6 +15,7 @@ import camera from '../assets/camera.svg';
import airplay from '../assets/airplay.svg';
import subtitle from '../assets/subtitle.svg';
import loading from '../assets/loading.svg';
import chromecast from '../assets/chromecast.svg';
const Icons = {
play: play,
@ -34,6 +35,7 @@ const Icons = {
subtitle: subtitle,
loading: loading,
airplay: airplay,
chromecast: chromecast,
};
export default Icons;

View File

@ -1,4 +1,4 @@
import '../css/index.scss';
import '../css/index.less';
import DPlayer from './player';
/* global DPLAYER_VERSION GIT_HASH */

View File

@ -12,6 +12,7 @@ export default (options) => {
lang: (navigator.language || navigator.browserLanguage).toLowerCase(),
screenshot: false,
airplay: true,
chromecast: false,
hotkey: true,
preload: 'metadata',
volume: 0.7,

View File

@ -79,6 +79,7 @@ class DPlayer {
if (this.options.danmaku) {
this.danmaku = new Danmaku({
player: this,
container: this.template.danmaku,
opacity: this.user.get('opacity'),
callback: () => {
@ -106,6 +107,7 @@ class DPlayer {
maximum: this.options.danmaku.maximum,
addition: this.options.danmaku.addition,
user: this.options.danmaku.user,
speedRate: this.options.danmaku.speedRate,
},
events: this.events,
tran: (msg) => this.tran(msg),

View File

@ -22,7 +22,8 @@ class Template {
current: true,
pic: this.options.video.pic,
screenshot: this.options.screenshot,
airplay: this.options.airplay,
airplay: utils.isSafari && !utils.isChrome ? this.options.airplay : false,
chromecast: this.options.chromecast,
preload: this.options.preload,
url: this.options.video.url,
subtitle: this.options.subtitle,
@ -80,6 +81,7 @@ class Template {
this.qualityList = this.container.querySelector('.dplayer-quality-list');
this.camareButton = this.container.querySelector('.dplayer-camera-icon');
this.airplayButton = this.container.querySelector('.dplayer-airplay-icon');
this.chromecastButton = this.container.querySelector('.dplayer-chromecast-icon');
this.subtitleButton = this.container.querySelector('.dplayer-subtitle-icon');
this.subtitleButtonInner = this.container.querySelector('.dplayer-subtitle-icon .dplayer-icon-content');
this.subtitle = this.container.querySelector('.dplayer-subtitle');

View File

@ -93,6 +93,8 @@ const utils = {
isChrome: /chrome/i.test(window.navigator.userAgent),
isSafari: /safari/i.test(window.navigator.userAgent),
storage: {
set: (key, value) => {
localStorage.setItem(key, value);

View File

@ -120,6 +120,11 @@
<span class="dplayer-icon-content">{{@ icons.airplay }}</span>
</div>
{{ /if }}
{{ if options.chromecast }}
<div class="dplayer-icon dplayer-chromecast-icon" data-balloon="{{ tran('ChromeCast') }}" data-balloon-pos="up">
<span class="dplayer-icon-content">{{@ icons.chromecast }}</span>
</div>
{{ /if }}
<div class="dplayer-comment">
<button class="dplayer-icon dplayer-comment-icon" data-balloon="{{ tran('Send danmaku') }}" data-balloon-pos="up">
<span class="dplayer-icon-content">{{@ icons.comment }}</span>

View File

@ -7,8 +7,15 @@
{{ if pic }}poster="{{ pic }}"{{ /if }}
{{ if screenshot || enableSubtitle }}crossorigin="anonymous"{{ /if }}
{{ if preload }}preload="{{ preload }}"{{ /if }}
{{ if url }}src="{{ url }}"{{ /if }}
{{ if airplay }}
nosrc
{{ else if url }}
src="{{ url }}"
{{ /if }}
>
{{ if airplay }}
<source src="{{ url }}">
{{ /if}}
{{ if enableSubtitle }}
<track kind="metadata" default src="{{ subtitle.url }}"></track>
{{ /if }}

View File

@ -1,9 +1,7 @@
const path = require('path');
const webpack = require('webpack');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const { GitRevisionPlugin } = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
mode: 'development',
@ -26,7 +24,13 @@ module.exports = {
resolve: {
modules: ['node_modules'],
extensions: ['.js', '.scss'],
extensions: ['.js', '.less'],
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
},
},
module: {
@ -45,7 +49,7 @@ module.exports = {
],
},
{
test: /\.scss$/,
test: /\.less$/,
use: [
'style-loader',
{
@ -57,10 +61,12 @@ module.exports = {
{
loader: 'postcss-loader',
options: {
plugins: [autoprefixer, cssnano],
postcssOptions: {
plugins: ['postcss-preset-env'],
},
},
},
'sass-loader',
'less-loader',
],
},
{
@ -82,17 +88,11 @@ module.exports = {
},
devServer: {
static: {
directory: path.join(__dirname, '..', 'demo'),
},
compress: true,
contentBase: path.resolve(__dirname, '..', 'demo'),
clientLogLevel: 'none',
quiet: false,
open: true,
historyApiFallback: {
disableDotRule: true,
},
watchOptions: {
ignored: /node_modules/,
},
},
plugins: [
@ -102,13 +102,6 @@ module.exports = {
}),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
},
performance: {
hints: false,
},

View File

@ -1,9 +1,7 @@
const path = require('path');
const webpack = require('webpack');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const { GitRevisionPlugin } = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
module.exports = {
mode: 'production',
@ -28,7 +26,13 @@ module.exports = {
resolve: {
modules: ['node_modules'],
extensions: ['.js', '.scss'],
extensions: ['.js', '.less'],
fallback: {
dgram: false,
fs: false,
net: false,
tls: false,
},
},
module: {
@ -48,7 +52,7 @@ module.exports = {
],
},
{
test: /\.scss$/,
test: /\.less$/,
use: [
'style-loader',
{
@ -60,10 +64,12 @@ module.exports = {
{
loader: 'postcss-loader',
options: {
plugins: [autoprefixer, cssnano],
postcssOptions: {
plugins: ['postcss-preset-env'],
},
},
},
'sass-loader',
'less-loader',
],
},
{
@ -90,11 +96,4 @@ module.exports = {
GIT_HASH: JSON.stringify(gitRevisionPlugin.version()),
}),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
},
};

9613
yarn.lock

File diff suppressed because it is too large Load Diff