diff --git a/docs/.vuepress/components/DPlayer.vue b/docs/.vuepress/components/DPlayer.vue index 47d8a1a..d5c9d2c 100644 --- a/docs/.vuepress/components/DPlayer.vue +++ b/docs/.vuepress/components/DPlayer.vue @@ -79,11 +79,17 @@ export default { }, mounted: function () { if (this.immediate) { - this.dplayer = new DPlayer(this.options); + if (!window) { + this.dplayer = new DPlayer(this.options); + } else { + window.onload = () => { + this.dplayer = new DPlayer(this.options); + } + } } }, beforeDestroy: function () { - this.dplayer.destroy(); + this.dplayer && this.dplayer.destroy(); } } diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 4402be9..2471cda 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -45,7 +45,7 @@ module.exports = { nav: [ { text: '指南', - link: '/zh/', + link: '/zh/guide/', }, { text: '生态', @@ -66,7 +66,7 @@ module.exports = { nav: [ { text: 'Guide', - link: '/', + link: '/guide/', }, { text: 'Ecosystem', diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl index 29037bd..5697a41 100644 --- a/docs/.vuepress/styles/index.styl +++ b/docs/.vuepress/styles/index.styl @@ -33,4 +33,16 @@ a { #dplayer { margin-top: -1.5rem; margin-bottom: 1rem; +} + +.hero .description { + display: none; +} + +.hero .action { + display: none; +} + +.hero.custom .action { + display: block; } \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index b7a3e34..89a28fa 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,762 +1,15 @@ --- -sidebar: auto +home: true +actionText: Get Started → +actionLink: /guide/ +footer: MIT Licensed | Made with love by DIYgod --- -# Guide - - - - - -# DPlayer +
+ +
-🍭 Wow, such a lovely HTML5 danmaku video player - - - -  - -## Special Thanks - -### Special Sponsors - -  - - - - - -  - - - - - -### Sponsors - - - - - -## Installation - -Using npm: - -``` -npm install dplayer --save -``` - -Using Yarn: - -``` -yarn add dplayer -``` - -## Quick Start - -At first, let's initialize a simplest DPlayer - -Load DPlayer files - -```html - -
- -``` - -Or work with module bundler: - -```js -import 'dplayer/dist/DPlayer.min.css'; -import DPlayer from 'dplayer'; - -const dp = new DPlayer(options); -``` - -Initialization in js: - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - screenshot: true, - video: { - url: 'demo.mp4', - pic: 'demo.jpg', - thumbnails: 'thumbnails.jpg' - }, - subtitle: { - url: 'webvtt.vtt' - }, - danmaku: { - id: 'demo', - api: 'https://api.prprpr.me/dplayer/' - } -}); -``` - -## Options - -You can custom your player instance by those options - -Name | Default | Description -----|-------|---- -container | document.querySelector('.dplayer') | player container -live | false | enable live mode, see [#live](#live) -autoplay | false | video autoplay -theme | '#b7daff' | main color -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 -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 -logo | - | showing logo in the top left corner, you can adjust its size and position by CSS -apiBackend | - | getting and sending danmaku in your way, see [#live](#live) -video | - | video info -video.quality | - | see [#Quality switching](#quality-switching) -video.defaultQuality | - | see [#Quality switching](#quality-switching) -video.url | - | video url -video.pic | - | video poster -video.thumbnails | - | video thumbnails, generated by [DPlayer-thumbnails](https://github.com/MoePlayer/DPlayer-thumbnails) -video.type | 'auto' | values: 'auto', 'hls', 'flv', 'dash', 'webtorrent', 'normal' or other custom type, see [#MSE support](#mse-support) -video.customType | - | custom video type, see [#MSE support](#mse-support) -subtitle | - | external subtitle -subtitle.url | `required` | subtitle url -subtitle.type | 'webvtt' | subtitle type, values: 'webvtt', 'ass', but only webvtt is supported for now -subtitle.fontSize | '20px' | subtitle font size -subtitle.bottom | '40px' | the distance between the subtitle and player bottom, values like: '10px' '10%' -subtitle.color | '#fff' | subtitle color -danmaku | - | showing danmaku -danmaku.id | `required` | danamku pool id, it must be unique -danmaku.api | `required` | see [#Danmaku API](#danmaku-api) -danmaku.token | - | back end verification token -danmaku.maximum | - | danmaku maximum quantity -danmaku.addition | - | additional danmaku, see [#bilibili danmaku](#bilibili-danmaku) -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 -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 - -```js -const dp = new DPlayer({ - container: document.getElementById('player'), - autoplay: false, - theme: '#FADFA3', - loop: true, - lang: 'zh-cn', - screenshot: true, - hotkey: true, - preload: 'auto', - logo: 'logo.png', - volume: 0.7, - mutex: true, - video: { - url: 'dplayer.mp4', - pic: 'dplayer.png', - thumbnails: 'thumbnails.jpg', - type: 'auto' - }, - subtitle: { - url: 'dplayer.vtt', - type: 'webvtt', - fontSize: '25px', - bottom: '10%', - color: '#b7daff' - }, - danmaku: { - id: '9E2E3368B56CDBB4', - api: 'https://api.prprpr.me/dplayer/', - token: 'tokendemo', - maximum: 1000, - addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=4157142'], - user: 'DIYgod', - bottom: '15%', - unlimited: true - }, - contextmenu: [ - { - text: 'custom1', - link: 'https://github.com/DIYgod/DPlayer' - }, - { - text: 'custom2', - click: (player) => { - console.log(player); - } - } - ], - highlight: [ - { - text: 'marker for 20s', - time: 20 - }, - { - text: 'marker for 2mins', - time: 120 - } - ] -}); -``` - -## API - -+ `dp.play()`: play video - -+ `dp.pause()`: pause video - -+ `dp.seek(time: number)`: seek to specified time - - ```js - dp.seek(100); - ``` - -+ `dp.toggle()`: toggle between play and pause - -+ `dp.on(event: string, handler: function)`: bind video and player events, [see more details](http://dplayer.js.org/#/home?id=event-binding) - -+ `dp.switchVideo(video, danmaku)`: switch to a new video - - ```js - dp.switchVideo({ - url: 'second.mp4', - pic: 'second.png', - thumbnails: 'second.jpg' - }, { - id: 'test', - api: 'https://api.prprpr.me/dplayer/', - maximum: 3000, - user: 'DIYgod' - }); - ``` - -+ `dp.notice(text: string, time: number, opacity: number)`: show message, the unit of time is millisecond, the default of time is 2000, the default of opacity is 0.8 - - ```js - dp.notice('Amazing player', 2000, 0.8); - ``` - -+ `dp.switchQuality(index: number)`: switch quality - -+ `dp.destroy()`: destroy player - -+ `dp.speed(rate: number)`: set video speed - -+ `dp.volume(percentage: number, nostorage: boolean, nonotice: boolean)`: set video volume - - ```js - dp.volume(0.1, true, false); - ``` - -+ `dp.video`: native video - - + `dp.video.currentTime`: returns the current playback position - - + `dp.video.duration`: returns video total time - - + `dp.video.paused`: returns whether the video paused - - + most [native api](http://www.w3schools.com/tags/ref_av_dom.asp) are supported - -+ `dp.danmaku` - - + `dp.danmaku.send(danmaku, callback: function)`: submit a new danmaku to back end - - ```js - dp.danmaku.send({ - text: 'dplayer is amazing', - color: '#b7daff', - type: 'right' // should be `top` `bottom` or `right` - }, function () { - console.log('success'); - }); - ``` - - + `dp.danmaku.draw(danmaku)`: draw a new danmaku to player in real time - - ```js - dp.danmaku.draw({ - text: 'DIYgod is amazing', - color: '#fff', - type: 'top' - }); - ``` - - + `dp.danmaku.opacity(percentage: number)`: set danmaku opacity, opacity should between 0 and 1 - - ```js - dp.danmaku.opacity(0.5); - ``` - - + `dp.danmaku.clear()`: clear all danmakus - - + `dp.danmaku.hide()`: hide danmaku - - + `dp.danmaku.show()`: show danmaku - -+ `dp.fullScreen`: two type: `web` or `browser`, the default one is `browser` - - + `dp.fullScreen.request(type: string)`: request fullscreen - - ```js - dp.fullScreen.request('web'); - ``` - - + `dp.fullScreen.cancel(type: string)`: cancel fullscreen - - ```js - dp.fullScreen.cancel('web'); - ``` - -## Event binding - -`dp.on(event, handler)` - -```js -dp.on('ended', function () { - console.log('player ended'); -}); -``` - -Video events - -- abort -- canplay -- canplaythrough -- durationchange -- emptied -- ended -- error -- loadeddata -- loadedmetadata -- loadstart -- mozaudioavailable -- pause -- play -- playing -- progress -- ratechange -- seeked -- seeking -- stalled -- suspend -- timeupdate -- volumechange -- waiting - -Player events - -- screenshot -- thumbnails_show -- thumbnails_hide -- danmaku_show -- danmaku_hide -- danmaku_clear -- danmaku_loaded -- danmaku_send -- danmaku_opacity -- contextmenu_show -- contextmenu_hide -- notice_show -- notice_hide -- quality_start -- quality_end -- destroy -- resize -- fullscreen -- fullscreen_cancel -- webfullscreen -- webfullscreen_cancel -- subtitle_show -- subtitle_hide -- subtitle_change - -## Quality switching - -Set video url and video type in `video.quality`, set default quality by `video.defaultQuality`. - - - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - quality: [{ - name: 'HD', - url: 'demo.m3u8', - type: 'hls' - }, { - name: 'SD', - url: 'demo.mp4', - type: 'normal' - }], - defaultQuality: 0, - pic: 'demo.png', - thumbnails: 'thumbnails.jpg', - } -}); -``` - -## Danmaku - -### Danmaku API - -`danmaku.api` - -**Ready-made API** - -url: https://api.prprpr.me/dplayer/ - -Daily backup data: [DPlayer-data](https://github.com/DIYgod/DPlayer-data) - -**Setting up yourself** - -[DPlayer-node](https://github.com/MoePlayer/DPlayer-node) - -### bilibili danmaku - -`danmaku.addition` - -API: - -```js -const option = { - danmaku: { - // ... - addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=[aid]'] - } -} -``` - -## MSE support - -### HLS - -It requires the library [hls.js](https://github.com/video-dev/hls.js) and it should be loaded before `DPlayer.min.js`. - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.m3u8', - type: 'hls' - } -}); -``` - -```js -// another way, use customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.m3u8', - type: 'customHls', - customType: { - 'customHls': function (video, player) { - const hls = new Hls(); - hls.loadSource(video.src); - hls.attachMedia(video); - } - } - } -}); -``` - -### MPEG DASH - -It requires the library [dash.js](https://github.com/Dash-Industry-Forum/dash.js) and it should be loaded before `DPlayer.min.js`. - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.mpd', - type: 'dash' - } -}); -``` - -```js -// another way, use customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.mpd', - type: 'customDash', - customType: { - 'customDash': function (video, player) { - dashjs.MediaPlayer().create().initialize(video, video.src, false); - } - } - } -}); -``` - -### MPEG DASH (Shaka) - -It requires the library [shaka-player](https://github.com/google/shaka-player) and it should be loaded before `DPlayer.min.js`. - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - screenshot: true, - video: { - url: 'demo.mpd', - type: 'shakaDash', - customType: { - 'shakaDash': function (video, player) { - var src = video.src; - var playerShaka = new shaka.Player(video); // 将会修改 video.src - playerShaka.load(src); - } - } - } -}); -``` - -### FLV - -It requires the library [flv.js](https://github.com/Bilibili/flv.js) and it should be loaded before `DPlayer.min.js`. - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.flv', - type: 'flv' - } -}); -``` - -```js -// another way, use customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.flv', - type: 'customFlv', - customType: { - 'customFlv': function (video, player) { - const flvPlayer = flvjs.createPlayer({ - type: 'flv', - url: video.src - }); - flvPlayer.attachMediaElement(video); - flvPlayer.load(); - } - } - } -}); -``` - -### WebTorrent - -It requires the library [webtorrent](https://github.com/webtorrent/webtorrent) and it should be loaded before `DPlayer.min.js`. - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'magnet:demo', - type: 'webtorrent' - } -}); -``` - -```js -// another way, use customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'magnet:demo', - type: 'customWebTorrent', - customType: { - 'customWebTorrent': function (video, player) { - player.container.classList.add('dplayer-loading'); - const client = new WebTorrent(); - const torrentId = video.src; - client.add(torrentId, (torrent) => { - const file = torrent.files.find((file) => file.name.endsWith('.mp4')); - file.renderTo(video, { - autoplay: player.options.autoplay - }, () => { - player.container.classList.remove('dplayer-loading'); - }); - }); - } - } - } -}); -``` - -### Work with other MSE library - -DPlayer can work with any MSE library via `customType` option. - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4', - type: 'pearplayer', - customType: { - 'pearplayer': function (video, player) { - new PearPlayer(video, { - src: video.src, - autoplay: player.options.autoplay - }); - } - } - } -}); -``` - -## Live - -You can use DPlayer in live, but if you want live danmaku, you should prepare a WebSocket backend yourself. - - - -Init player: - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - live: true, - danmaku: true, - apiBackend: { - read: function (options) { - console.log('Pretend to connect WebSocket'); - callback(); - }, - send: function (options) { - console.log('Pretend to send danamku via WebSocket', options.data); - callback(); - } - }, - video: { - url: 'demo.m3u8', - type: 'hls' - } -}); -``` - -Draw danmaku after getting a danmaku via WebSocket: - -```js -const danmaku = { - text: 'Get a danamku via WebSocket', - color: '#fff', - type: 'right' -}; -dp.danmaku.draw(danmaku); -``` - -## FAQ - -### Why can't player be full screen? - -If player is contained in a iframe, try adding the `allowfullscreen` attribute to the iframe. - -For full browser support it should look like this: - -```html - -``` - -### Why can't player autoplay in some mobile browsers? - -Most mobile browsers forbid video autoplay, you wont be able to achieve it without hacks. +

Get Started →

\ No newline at end of file diff --git a/docs/guide.md b/docs/guide.md new file mode 100644 index 0000000..b7a3e34 --- /dev/null +++ b/docs/guide.md @@ -0,0 +1,762 @@ +--- +sidebar: auto +--- + +# Guide + + + + + + + + +# DPlayer + +🍭 Wow, such a lovely HTML5 danmaku video player + + + +  + +## Special Thanks + +### Special Sponsors + +  + + + + + +  + + + + + +### Sponsors + + + + + +## Installation + +Using npm: + +``` +npm install dplayer --save +``` + +Using Yarn: + +``` +yarn add dplayer +``` + +## Quick Start + +At first, let's initialize a simplest DPlayer + +Load DPlayer files + +```html + +
+ +``` + +Or work with module bundler: + +```js +import 'dplayer/dist/DPlayer.min.css'; +import DPlayer from 'dplayer'; + +const dp = new DPlayer(options); +``` + +Initialization in js: + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + screenshot: true, + video: { + url: 'demo.mp4', + pic: 'demo.jpg', + thumbnails: 'thumbnails.jpg' + }, + subtitle: { + url: 'webvtt.vtt' + }, + danmaku: { + id: 'demo', + api: 'https://api.prprpr.me/dplayer/' + } +}); +``` + +## Options + +You can custom your player instance by those options + +Name | Default | Description +----|-------|---- +container | document.querySelector('.dplayer') | player container +live | false | enable live mode, see [#live](#live) +autoplay | false | video autoplay +theme | '#b7daff' | main color +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 +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 +logo | - | showing logo in the top left corner, you can adjust its size and position by CSS +apiBackend | - | getting and sending danmaku in your way, see [#live](#live) +video | - | video info +video.quality | - | see [#Quality switching](#quality-switching) +video.defaultQuality | - | see [#Quality switching](#quality-switching) +video.url | - | video url +video.pic | - | video poster +video.thumbnails | - | video thumbnails, generated by [DPlayer-thumbnails](https://github.com/MoePlayer/DPlayer-thumbnails) +video.type | 'auto' | values: 'auto', 'hls', 'flv', 'dash', 'webtorrent', 'normal' or other custom type, see [#MSE support](#mse-support) +video.customType | - | custom video type, see [#MSE support](#mse-support) +subtitle | - | external subtitle +subtitle.url | `required` | subtitle url +subtitle.type | 'webvtt' | subtitle type, values: 'webvtt', 'ass', but only webvtt is supported for now +subtitle.fontSize | '20px' | subtitle font size +subtitle.bottom | '40px' | the distance between the subtitle and player bottom, values like: '10px' '10%' +subtitle.color | '#fff' | subtitle color +danmaku | - | showing danmaku +danmaku.id | `required` | danamku pool id, it must be unique +danmaku.api | `required` | see [#Danmaku API](#danmaku-api) +danmaku.token | - | back end verification token +danmaku.maximum | - | danmaku maximum quantity +danmaku.addition | - | additional danmaku, see [#bilibili danmaku](#bilibili-danmaku) +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 +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 + +```js +const dp = new DPlayer({ + container: document.getElementById('player'), + autoplay: false, + theme: '#FADFA3', + loop: true, + lang: 'zh-cn', + screenshot: true, + hotkey: true, + preload: 'auto', + logo: 'logo.png', + volume: 0.7, + mutex: true, + video: { + url: 'dplayer.mp4', + pic: 'dplayer.png', + thumbnails: 'thumbnails.jpg', + type: 'auto' + }, + subtitle: { + url: 'dplayer.vtt', + type: 'webvtt', + fontSize: '25px', + bottom: '10%', + color: '#b7daff' + }, + danmaku: { + id: '9E2E3368B56CDBB4', + api: 'https://api.prprpr.me/dplayer/', + token: 'tokendemo', + maximum: 1000, + addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=4157142'], + user: 'DIYgod', + bottom: '15%', + unlimited: true + }, + contextmenu: [ + { + text: 'custom1', + link: 'https://github.com/DIYgod/DPlayer' + }, + { + text: 'custom2', + click: (player) => { + console.log(player); + } + } + ], + highlight: [ + { + text: 'marker for 20s', + time: 20 + }, + { + text: 'marker for 2mins', + time: 120 + } + ] +}); +``` + +## API + ++ `dp.play()`: play video + ++ `dp.pause()`: pause video + ++ `dp.seek(time: number)`: seek to specified time + + ```js + dp.seek(100); + ``` + ++ `dp.toggle()`: toggle between play and pause + ++ `dp.on(event: string, handler: function)`: bind video and player events, [see more details](http://dplayer.js.org/#/home?id=event-binding) + ++ `dp.switchVideo(video, danmaku)`: switch to a new video + + ```js + dp.switchVideo({ + url: 'second.mp4', + pic: 'second.png', + thumbnails: 'second.jpg' + }, { + id: 'test', + api: 'https://api.prprpr.me/dplayer/', + maximum: 3000, + user: 'DIYgod' + }); + ``` + ++ `dp.notice(text: string, time: number, opacity: number)`: show message, the unit of time is millisecond, the default of time is 2000, the default of opacity is 0.8 + + ```js + dp.notice('Amazing player', 2000, 0.8); + ``` + ++ `dp.switchQuality(index: number)`: switch quality + ++ `dp.destroy()`: destroy player + ++ `dp.speed(rate: number)`: set video speed + ++ `dp.volume(percentage: number, nostorage: boolean, nonotice: boolean)`: set video volume + + ```js + dp.volume(0.1, true, false); + ``` + ++ `dp.video`: native video + + + `dp.video.currentTime`: returns the current playback position + + + `dp.video.duration`: returns video total time + + + `dp.video.paused`: returns whether the video paused + + + most [native api](http://www.w3schools.com/tags/ref_av_dom.asp) are supported + ++ `dp.danmaku` + + + `dp.danmaku.send(danmaku, callback: function)`: submit a new danmaku to back end + + ```js + dp.danmaku.send({ + text: 'dplayer is amazing', + color: '#b7daff', + type: 'right' // should be `top` `bottom` or `right` + }, function () { + console.log('success'); + }); + ``` + + + `dp.danmaku.draw(danmaku)`: draw a new danmaku to player in real time + + ```js + dp.danmaku.draw({ + text: 'DIYgod is amazing', + color: '#fff', + type: 'top' + }); + ``` + + + `dp.danmaku.opacity(percentage: number)`: set danmaku opacity, opacity should between 0 and 1 + + ```js + dp.danmaku.opacity(0.5); + ``` + + + `dp.danmaku.clear()`: clear all danmakus + + + `dp.danmaku.hide()`: hide danmaku + + + `dp.danmaku.show()`: show danmaku + ++ `dp.fullScreen`: two type: `web` or `browser`, the default one is `browser` + + + `dp.fullScreen.request(type: string)`: request fullscreen + + ```js + dp.fullScreen.request('web'); + ``` + + + `dp.fullScreen.cancel(type: string)`: cancel fullscreen + + ```js + dp.fullScreen.cancel('web'); + ``` + +## Event binding + +`dp.on(event, handler)` + +```js +dp.on('ended', function () { + console.log('player ended'); +}); +``` + +Video events + +- abort +- canplay +- canplaythrough +- durationchange +- emptied +- ended +- error +- loadeddata +- loadedmetadata +- loadstart +- mozaudioavailable +- pause +- play +- playing +- progress +- ratechange +- seeked +- seeking +- stalled +- suspend +- timeupdate +- volumechange +- waiting + +Player events + +- screenshot +- thumbnails_show +- thumbnails_hide +- danmaku_show +- danmaku_hide +- danmaku_clear +- danmaku_loaded +- danmaku_send +- danmaku_opacity +- contextmenu_show +- contextmenu_hide +- notice_show +- notice_hide +- quality_start +- quality_end +- destroy +- resize +- fullscreen +- fullscreen_cancel +- webfullscreen +- webfullscreen_cancel +- subtitle_show +- subtitle_hide +- subtitle_change + +## Quality switching + +Set video url and video type in `video.quality`, set default quality by `video.defaultQuality`. + + + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + quality: [{ + name: 'HD', + url: 'demo.m3u8', + type: 'hls' + }, { + name: 'SD', + url: 'demo.mp4', + type: 'normal' + }], + defaultQuality: 0, + pic: 'demo.png', + thumbnails: 'thumbnails.jpg', + } +}); +``` + +## Danmaku + +### Danmaku API + +`danmaku.api` + +**Ready-made API** + +url: https://api.prprpr.me/dplayer/ + +Daily backup data: [DPlayer-data](https://github.com/DIYgod/DPlayer-data) + +**Setting up yourself** + +[DPlayer-node](https://github.com/MoePlayer/DPlayer-node) + +### bilibili danmaku + +`danmaku.addition` + +API: + +```js +const option = { + danmaku: { + // ... + addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=[aid]'] + } +} +``` + +## MSE support + +### HLS + +It requires the library [hls.js](https://github.com/video-dev/hls.js) and it should be loaded before `DPlayer.min.js`. + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.m3u8', + type: 'hls' + } +}); +``` + +```js +// another way, use customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.m3u8', + type: 'customHls', + customType: { + 'customHls': function (video, player) { + const hls = new Hls(); + hls.loadSource(video.src); + hls.attachMedia(video); + } + } + } +}); +``` + +### MPEG DASH + +It requires the library [dash.js](https://github.com/Dash-Industry-Forum/dash.js) and it should be loaded before `DPlayer.min.js`. + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.mpd', + type: 'dash' + } +}); +``` + +```js +// another way, use customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.mpd', + type: 'customDash', + customType: { + 'customDash': function (video, player) { + dashjs.MediaPlayer().create().initialize(video, video.src, false); + } + } + } +}); +``` + +### MPEG DASH (Shaka) + +It requires the library [shaka-player](https://github.com/google/shaka-player) and it should be loaded before `DPlayer.min.js`. + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + screenshot: true, + video: { + url: 'demo.mpd', + type: 'shakaDash', + customType: { + 'shakaDash': function (video, player) { + var src = video.src; + var playerShaka = new shaka.Player(video); // 将会修改 video.src + playerShaka.load(src); + } + } + } +}); +``` + +### FLV + +It requires the library [flv.js](https://github.com/Bilibili/flv.js) and it should be loaded before `DPlayer.min.js`. + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.flv', + type: 'flv' + } +}); +``` + +```js +// another way, use customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.flv', + type: 'customFlv', + customType: { + 'customFlv': function (video, player) { + const flvPlayer = flvjs.createPlayer({ + type: 'flv', + url: video.src + }); + flvPlayer.attachMediaElement(video); + flvPlayer.load(); + } + } + } +}); +``` + +### WebTorrent + +It requires the library [webtorrent](https://github.com/webtorrent/webtorrent) and it should be loaded before `DPlayer.min.js`. + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'magnet:demo', + type: 'webtorrent' + } +}); +``` + +```js +// another way, use customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'magnet:demo', + type: 'customWebTorrent', + customType: { + 'customWebTorrent': function (video, player) { + player.container.classList.add('dplayer-loading'); + const client = new WebTorrent(); + const torrentId = video.src; + client.add(torrentId, (torrent) => { + const file = torrent.files.find((file) => file.name.endsWith('.mp4')); + file.renderTo(video, { + autoplay: player.options.autoplay + }, () => { + player.container.classList.remove('dplayer-loading'); + }); + }); + } + } + } +}); +``` + +### Work with other MSE library + +DPlayer can work with any MSE library via `customType` option. + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4', + type: 'pearplayer', + customType: { + 'pearplayer': function (video, player) { + new PearPlayer(video, { + src: video.src, + autoplay: player.options.autoplay + }); + } + } + } +}); +``` + +## Live + +You can use DPlayer in live, but if you want live danmaku, you should prepare a WebSocket backend yourself. + + + +Init player: + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + live: true, + danmaku: true, + apiBackend: { + read: function (options) { + console.log('Pretend to connect WebSocket'); + callback(); + }, + send: function (options) { + console.log('Pretend to send danamku via WebSocket', options.data); + callback(); + } + }, + video: { + url: 'demo.m3u8', + type: 'hls' + } +}); +``` + +Draw danmaku after getting a danmaku via WebSocket: + +```js +const danmaku = { + text: 'Get a danamku via WebSocket', + color: '#fff', + type: 'right' +}; +dp.danmaku.draw(danmaku); +``` + +## FAQ + +### Why can't player be full screen? + +If player is contained in a iframe, try adding the `allowfullscreen` attribute to the iframe. + +For full browser support it should look like this: + +```html + +``` + +### Why can't player autoplay in some mobile browsers? + +Most mobile browsers forbid video autoplay, you wont be able to achieve it without hacks. diff --git a/docs/zh/README.md b/docs/zh/README.md index 1428cca..2732728 100644 --- a/docs/zh/README.md +++ b/docs/zh/README.md @@ -1,747 +1,15 @@ --- -sidebar: auto +home: true +actionText: Get Started → +actionLink: /guide/ +footer: MIT Licensed | Made with love by DIYgod --- -# 指南 - - - - -# DPlayer +
+ +
-🍭 Wow, such a lovely HTML5 danmaku video player - - - -  - -## Special Thanks - -### Special Sponsors - -  - - - - - -  - - - - - -### Sponsors - - - - - -## 安装 - -使用 npm: - -``` -npm install dplayer --save -``` - -使用 Yarn: - -``` -yarn add dplayer -``` - -## 快速开始 - -我们先尝试初始化一个最简单的 DPlayer - -加载播放器文件: - -```html - -
- -``` - -或者使用模块管理器: - -```js -import 'dplayer/dist/DPlayer.min.css'; -import DPlayer from 'dplayer'; - -const dp = new DPlayer(options); -``` - -在 js 里初始化: - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.mp4' - }, -}); -``` - -一个最简单的 DPlayer 就初始化好了,它只有最基本的视频播放功能 - -## 参数 - -DPlayer 有丰富的参数可以自定义你的播放器实例 - -名称 | 默认值 | 描述 -----|-------|---- -container | document.querySelector('.dplayer') | 播放器容器元素 -live | false | 开启直播模式, 见[#直播](#直播) -autoplay | false | 视频自动播放 -theme | '#b7daff' | 主题色 -loop | false | 视频循环播放 -lang | navigator.language.toLowerCase() | 可选值: 'en', 'zh-cn', 'zh-tw' -screenshot | false | 开启截图,如果开启,视频和视频封面需要允许跨域 -hotkey | true | 开启热键,支持快进、快退、音量控制、播放暂停 -preload | 'auto' | 视频预加载,可选值: 'none', 'metadata', 'auto' -volume | 0.7 | 默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 -logo | - | 在左上角展示一个 logo,你可以通过 CSS 调整它的大小和位置 -apiBackend | - | 自定义获取和发送弹幕行为,见[#直播](#直播) -video | - | 视频信息 -video.quality | - | 见[#清晰度切换](#清晰度切换) -video.defaultQuality | - | 见[#清晰度切换](#清晰度切换) -video.url | - | 视频链接 -video.pic | - | 视频封面 -video.thumbnails | - | 视频缩略图,可以使用 [DPlayer-thumbnails](https://github.com/MoePlayer/DPlayer-thumbnails) 生成 -video.type | 'auto' | 可选值: 'auto', 'hls', 'flv', 'dash', 'webtorrent', 'normal' 或其他自定义类型, 见[#MSE 支持](#mse-支持) -video.customType | - | 自定义类型, 见[#MSE 支持](#mse-支持) -subtitle | - | 外挂字幕 -subtitle.url | `required` | 字幕链接 -subtitle.type | 'webvtt' | 字幕类型,可选值: 'webvtt', 'ass',目前只支持 webvtt -subtitle.fontSize | '20px' | 字幕字号 -subtitle.bottom | '40px' | 字幕距离播放器底部的距离,取值形如: '10px' '10%' -subtitle.color | '#fff' | 字幕颜色 -danmaku | - | 显示弹幕 -danmaku.id | `required` | 弹幕池id,必须唯一 -danmaku.api | `required` | 见[#弹幕接口](#弹幕接口) -danmaku.token | - | 弹幕后端验证 token -danmaku.maximum | - | 弹幕最大数量 -danmaku.addition | - | 额外外挂弹幕,见[#bilibili 弹幕](#bilibili-弹幕) -danmaku.user | 'DIYgod' | 弹幕用户名 -danmaku.bottom | - | 弹幕距离播放器底部的距离,防止遮挡字幕,取值形如: '10px' '10%' -danmaku.unlimited | false | 海量弹幕模式,即使重叠也展示全部弹幕,请注意播放器会记忆用户设置,用户手动设置后即失效 -contextmenu | [] | 自定义右键菜单 -highlight | [] | 自定义进度条提示点 -mutex | true | 互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器 - -```js -const dp = new DPlayer({ - container: document.getElementById('player'), - autoplay: false, - theme: '#FADFA3', - loop: true, - lang: 'zh-cn', - screenshot: true, - hotkey: true, - preload: 'auto', - logo: 'logo.png', - volume: 0.7, - mutex: true, - video: { - url: 'dplayer.mp4', - pic: 'dplayer.png', - thumbnails: 'thumbnails.jpg', - type: 'auto' - }, - subtitle: { - url: 'dplayer.vtt', - type: 'webvtt', - fontSize: '25px', - bottom: '10%', - color: '#b7daff' - }, - danmaku: { - id: '9E2E3368B56CDBB4', - api: 'https://api.prprpr.me/dplayer/', - token: 'tokendemo', - maximum: 1000, - addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=4157142'], - user: 'DIYgod', - bottom: '15%', - unlimited: true - }, - contextmenu: [ - { - text: 'custom1', - link: 'https://github.com/DIYgod/DPlayer' - }, - { - text: 'custom2', - click: (player) => { - console.log(player); - } - } - ], - highlight: [ - { - time: 20, - text: '这是第 20 秒' - }, - { - time: 120, - text: '这是 2 分钟' - } - ] -}); -``` - -## API - -+ `dp.play()`: 播放视频 - -+ `dp.pause()`: 暂停视频 - -+ `dp.seek(time: number)`: 跳转到特定时间 - - ```js - dp.seek(100); - ``` - -+ `dp.toggle()`: 切换播放和暂停 - -+ `dp.on(event: string, handler: function)`: 绑定视频和播放器事件,见[#事件绑定](#事件绑定) - -+ `dp.switchVideo(video, danmaku)`: 切换到其他视频 - - ```js - dp.switchVideo({ - url: 'second.mp4', - pic: 'second.png', - thumbnails: 'second.jpg' - }, { - id: 'test', - api: 'https://api.prprpr.me/dplayer/', - maximum: 3000, - user: 'DIYgod' - }); - ``` - -+ `dp.notice(text: string, time: number)`: 显示通知,时间的单位为毫秒,默认时间2000毫秒,默认透明度0.8 - -+ `dp.switchQuality(index: number)`: 切换清晰度 - -+ `dp.destroy()`: 销毁播放器 - -+ `dp.speed(rate: number)`: 设置视频速度 - -+ `dp.volume(percentage: number, nostorage: boolean, nonotice: boolean)`: 设置视频音量 - - ```js - dp.volume(0.1, true, false); - ``` - -+ `dp.video`: 原生 video - - + `dp.video.currentTime`: 返回视频当前播放时间 - - + `dp.video.duration`: 返回视频总时间 - - + `dp.video.paused`: 返回视频是否暂停 - - + 支持大多数[原生video接口](http://www.w3schools.com/tags/ref_av_dom.asp) - -+ `dp.danmaku` - - + `dp.danmaku.send(danmaku, callback: function)`: 提交一个新弹幕 - - ```js - dp.danmaku.send({ - text: 'dplayer is amazing', - color: '#b7daff', - type: 'right' // should be `top` `bottom` or `right` - }, function () { - console.log('success'); - }); - ``` - - + `dp.danmaku.draw(danmaku)`: 实时绘制一个新弹幕 - - ```js - dp.danmaku.draw({ - text: 'DIYgod is amazing', - color: '#fff', - type: 'top' - }); - ``` - - + `dp.danmaku.opacity(percentage: number)`: 设置弹幕透明度,透明度值在 0 到 1 之间 - - ```js - dp.danmaku.opacity(0.5); - ``` - - + `dp.danmaku.clear()`: 清除所有弹幕 - - + `dp.danmaku.hide()`: 隐藏弹幕 - - + `dp.danmaku.show()`: 显示弹幕 - -+ `dp.fullScreen`: 两个类型:`web` 和 `browser`,默认类型是 `browser` - - + `dp.fullScreen.request(type: string)`: 进入全屏 - - ```js - dp.fullScreen.request('web'); - ``` - - + `dp.fullScreen.cancel(type: string)`: 退出全屏 - - ```js - dp.fullScreen.cancel('web'); - ``` - -## 事件绑定 - -`dp.on(event, handler)` - -```js -dp.on('ended', function () { - console.log('player ended'); -}); -``` - -视频事件 - -- abort -- canplay -- canplaythrough -- durationchange -- emptied -- ended -- error -- loadeddata -- loadedmetadata -- loadstart -- mozaudioavailable -- pause -- play -- playing -- progress -- ratechange -- seeked -- seeking -- stalled -- suspend -- timeupdate -- volumechange -- waiting - -播放器事件 - -- screenshot -- thumbnails_show -- thumbnails_hide -- danmaku_show -- danmaku_hide -- danmaku_clear -- danmaku_loaded -- danmaku_send -- danmaku_opacity -- contextmenu_show -- contextmenu_hide -- notice_show -- notice_hide -- quality_start -- quality_end -- destroy -- resize -- fullscreen -- fullscreen_cancel -- subtitle_show -- subtitle_hide -- subtitle_change - -## 清晰度切换 - -在 `video.quality` 里设置不同清晰度的视频链接和类型,`video.defaultQuality` 设置默认清晰度 - - - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - quality: [{ - name: 'HD', - url: 'demo.m3u8', - type: 'hls' - }, { - name: 'SD', - url: 'demo.mp4', - type: 'normal' - }], - defaultQuality: 0, - pic: 'demo.png', - thumbnails: 'thumbnails.jpg', - } -}); -``` - -## 弹幕 - -### 弹幕接口 - -`danmaku.api` - -**现成的接口** - -链接: https://api.prprpr.me/dplayer/ - -每日备份: [DPlayer-data](https://github.com/DIYgod/DPlayer-data) - -**自己搭建** - -[DPlayer-node](https://github.com/MoePlayer/DPlayer-node) - -### bilibili 弹幕 - -`danmaku.addition` - -API: - -```js -const option = { - danmaku: { - // ... - addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=[aid]'] - } -} -``` - -## MSE 支持 - -### HLS - -需要在 `DPlayer.min.js` 前面加载 [hls.js](https://github.com/video-dev/hls.js)。 - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.m3u8', - type: 'hls' - } -}); -``` - -```js -// 另一种方式,使用 customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.m3u8', - type: 'customHls', - customType: { - 'customHls': function (video, player) { - const hls = new Hls(); - hls.loadSource(video.src); - hls.attachMedia(video); - } - } - } -}); -``` - -### MPEG DASH - -需要在 `DPlayer.min.js` 前面加载 [dash.js](https://github.com/Dash-Industry-Forum/dash.js)。 - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.mpd', - type: 'dash' - } -}); -``` - -```js -// 另一种方式,使用 customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.mpd', - type: 'customDash', - customType: { - 'customDash': function (video, player) { - dashjs.MediaPlayer().create().initialize(video, video.src, false); - } - } - } -}); -``` - -### MPEG DASH (Shaka) - -需要在 `DPlayer.min.js` 前面加载 [shaka-player.compiled.js](https://github.com/google/shaka-player)。 - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - screenshot: true, - video: { - url: 'demo.mpd', - type: 'shakaDash', - customType: { - 'shakaDash': function (video, player) { - var src = video.src; - var playerShaka = new shaka.Player(video); // 将会修改 video.src - playerShaka.load(src); - } - } - } -}); -``` - -### FLV - -需要在 `DPlayer.min.js` 前面加载 [flv.js](https://github.com/Bilibili/flv.js)。 - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.flv', - type: 'flv' - } -}); -``` - -```js -// 另一种方式,使用 customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'demo.flv', - type: 'customFlv', - customType: { - 'customFlv': function (video, player) { - const flvPlayer = flvjs.createPlayer({ - type: 'flv', - url: video.src - }); - flvPlayer.attachMediaElement(video); - flvPlayer.load(); - } - } - } -}); -``` - -### WebTorrent - -需要在 `DPlayer.min.js` 前面加载 [webtorrent](https://github.com/webtorrent/webtorrent)。 - - - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'magnet:demo', - type: 'webtorrent' - } -}); -``` - -```js -// 另一种方式,使用 customType -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'magnet:demo', - type: 'customWebTorrent', - customType: { - 'customWebTorrent': function (video, player) { - player.container.classList.add('dplayer-loading'); - const client = new WebTorrent(); - const torrentId = video.src; - client.add(torrentId, (torrent) => { - const file = torrent.files.find((file) => file.name.endsWith('.mp4')); - file.renderTo(video, { - autoplay: player.options.autoplay - }, () => { - player.container.classList.remove('dplayer-loading'); - }); - }); - } - } - } -}); -``` - -### 配合其他 MSE 库使用 - -DPlayer 可以通过 `customType` 参数与任何 MSE 库一起使用 - -```html - -
- - -``` - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - video: { - url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4', - type: 'pearplayer', - customType: { - 'pearplayer': function (video, player) { - new PearPlayer(video, { - src: video.src, - autoplay: player.options.autoplay - }); - } - } - } -}); -``` - -## 直播 - -你可以把 DPlayer 用在直播当中,但如果你想要直播弹幕,你需要自己准备一个 WebSocket 后端。 - - - -初始化播放器: - -```js -const dp = new DPlayer({ - container: document.getElementById('dplayer'), - live: true, - danmaku: true, - apiBackend: { - read: function (endpoint, callback) { - console.log('Pretend to connect WebSocket'); - callback(); - }, - send: function (endpoint, danmakuData, callback) { - console.log('Pretend to send danamku via WebSocket', danmakuData); - callback(); - } - }, - video: { - url: 'demo.m3u8', - type: 'hls' - } -}); -``` - -通过 WebSocket 获取到弹幕之后,通过 `dp.danmaku.draw` 绘制弹幕: - -```js -const danmaku = { - text: 'Get a danamku via WebSocket', - color: '#fff', - type: 'right' -}; -dp.danmaku.draw(danmaku); -``` - -## 常见问题 - -### 为什么播放器不能全屏? - -如果播放器被包含在 iframe 里,尝试在 iframe 上添加 `allowfullscreen` 属性。 - -为了完善的浏览器兼容性,它应该是这样: - -```html - -``` - -### 为什么播放器不能在手机上自动播放? - -大多数移动端浏览器禁止了视频自动播放。 +

快速上手 →

\ No newline at end of file diff --git a/docs/zh/guide.md b/docs/zh/guide.md new file mode 100644 index 0000000..1428cca --- /dev/null +++ b/docs/zh/guide.md @@ -0,0 +1,747 @@ +--- +sidebar: auto +--- +# 指南 + + + + + + + + +# DPlayer + +🍭 Wow, such a lovely HTML5 danmaku video player + + + +  + +## Special Thanks + +### Special Sponsors + +  + + + + + +  + + + + + +### Sponsors + + + + + +## 安装 + +使用 npm: + +``` +npm install dplayer --save +``` + +使用 Yarn: + +``` +yarn add dplayer +``` + +## 快速开始 + +我们先尝试初始化一个最简单的 DPlayer + +加载播放器文件: + +```html + +
+ +``` + +或者使用模块管理器: + +```js +import 'dplayer/dist/DPlayer.min.css'; +import DPlayer from 'dplayer'; + +const dp = new DPlayer(options); +``` + +在 js 里初始化: + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.mp4' + }, +}); +``` + +一个最简单的 DPlayer 就初始化好了,它只有最基本的视频播放功能 + +## 参数 + +DPlayer 有丰富的参数可以自定义你的播放器实例 + +名称 | 默认值 | 描述 +----|-------|---- +container | document.querySelector('.dplayer') | 播放器容器元素 +live | false | 开启直播模式, 见[#直播](#直播) +autoplay | false | 视频自动播放 +theme | '#b7daff' | 主题色 +loop | false | 视频循环播放 +lang | navigator.language.toLowerCase() | 可选值: 'en', 'zh-cn', 'zh-tw' +screenshot | false | 开启截图,如果开启,视频和视频封面需要允许跨域 +hotkey | true | 开启热键,支持快进、快退、音量控制、播放暂停 +preload | 'auto' | 视频预加载,可选值: 'none', 'metadata', 'auto' +volume | 0.7 | 默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 +logo | - | 在左上角展示一个 logo,你可以通过 CSS 调整它的大小和位置 +apiBackend | - | 自定义获取和发送弹幕行为,见[#直播](#直播) +video | - | 视频信息 +video.quality | - | 见[#清晰度切换](#清晰度切换) +video.defaultQuality | - | 见[#清晰度切换](#清晰度切换) +video.url | - | 视频链接 +video.pic | - | 视频封面 +video.thumbnails | - | 视频缩略图,可以使用 [DPlayer-thumbnails](https://github.com/MoePlayer/DPlayer-thumbnails) 生成 +video.type | 'auto' | 可选值: 'auto', 'hls', 'flv', 'dash', 'webtorrent', 'normal' 或其他自定义类型, 见[#MSE 支持](#mse-支持) +video.customType | - | 自定义类型, 见[#MSE 支持](#mse-支持) +subtitle | - | 外挂字幕 +subtitle.url | `required` | 字幕链接 +subtitle.type | 'webvtt' | 字幕类型,可选值: 'webvtt', 'ass',目前只支持 webvtt +subtitle.fontSize | '20px' | 字幕字号 +subtitle.bottom | '40px' | 字幕距离播放器底部的距离,取值形如: '10px' '10%' +subtitle.color | '#fff' | 字幕颜色 +danmaku | - | 显示弹幕 +danmaku.id | `required` | 弹幕池id,必须唯一 +danmaku.api | `required` | 见[#弹幕接口](#弹幕接口) +danmaku.token | - | 弹幕后端验证 token +danmaku.maximum | - | 弹幕最大数量 +danmaku.addition | - | 额外外挂弹幕,见[#bilibili 弹幕](#bilibili-弹幕) +danmaku.user | 'DIYgod' | 弹幕用户名 +danmaku.bottom | - | 弹幕距离播放器底部的距离,防止遮挡字幕,取值形如: '10px' '10%' +danmaku.unlimited | false | 海量弹幕模式,即使重叠也展示全部弹幕,请注意播放器会记忆用户设置,用户手动设置后即失效 +contextmenu | [] | 自定义右键菜单 +highlight | [] | 自定义进度条提示点 +mutex | true | 互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器 + +```js +const dp = new DPlayer({ + container: document.getElementById('player'), + autoplay: false, + theme: '#FADFA3', + loop: true, + lang: 'zh-cn', + screenshot: true, + hotkey: true, + preload: 'auto', + logo: 'logo.png', + volume: 0.7, + mutex: true, + video: { + url: 'dplayer.mp4', + pic: 'dplayer.png', + thumbnails: 'thumbnails.jpg', + type: 'auto' + }, + subtitle: { + url: 'dplayer.vtt', + type: 'webvtt', + fontSize: '25px', + bottom: '10%', + color: '#b7daff' + }, + danmaku: { + id: '9E2E3368B56CDBB4', + api: 'https://api.prprpr.me/dplayer/', + token: 'tokendemo', + maximum: 1000, + addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=4157142'], + user: 'DIYgod', + bottom: '15%', + unlimited: true + }, + contextmenu: [ + { + text: 'custom1', + link: 'https://github.com/DIYgod/DPlayer' + }, + { + text: 'custom2', + click: (player) => { + console.log(player); + } + } + ], + highlight: [ + { + time: 20, + text: '这是第 20 秒' + }, + { + time: 120, + text: '这是 2 分钟' + } + ] +}); +``` + +## API + ++ `dp.play()`: 播放视频 + ++ `dp.pause()`: 暂停视频 + ++ `dp.seek(time: number)`: 跳转到特定时间 + + ```js + dp.seek(100); + ``` + ++ `dp.toggle()`: 切换播放和暂停 + ++ `dp.on(event: string, handler: function)`: 绑定视频和播放器事件,见[#事件绑定](#事件绑定) + ++ `dp.switchVideo(video, danmaku)`: 切换到其他视频 + + ```js + dp.switchVideo({ + url: 'second.mp4', + pic: 'second.png', + thumbnails: 'second.jpg' + }, { + id: 'test', + api: 'https://api.prprpr.me/dplayer/', + maximum: 3000, + user: 'DIYgod' + }); + ``` + ++ `dp.notice(text: string, time: number)`: 显示通知,时间的单位为毫秒,默认时间2000毫秒,默认透明度0.8 + ++ `dp.switchQuality(index: number)`: 切换清晰度 + ++ `dp.destroy()`: 销毁播放器 + ++ `dp.speed(rate: number)`: 设置视频速度 + ++ `dp.volume(percentage: number, nostorage: boolean, nonotice: boolean)`: 设置视频音量 + + ```js + dp.volume(0.1, true, false); + ``` + ++ `dp.video`: 原生 video + + + `dp.video.currentTime`: 返回视频当前播放时间 + + + `dp.video.duration`: 返回视频总时间 + + + `dp.video.paused`: 返回视频是否暂停 + + + 支持大多数[原生video接口](http://www.w3schools.com/tags/ref_av_dom.asp) + ++ `dp.danmaku` + + + `dp.danmaku.send(danmaku, callback: function)`: 提交一个新弹幕 + + ```js + dp.danmaku.send({ + text: 'dplayer is amazing', + color: '#b7daff', + type: 'right' // should be `top` `bottom` or `right` + }, function () { + console.log('success'); + }); + ``` + + + `dp.danmaku.draw(danmaku)`: 实时绘制一个新弹幕 + + ```js + dp.danmaku.draw({ + text: 'DIYgod is amazing', + color: '#fff', + type: 'top' + }); + ``` + + + `dp.danmaku.opacity(percentage: number)`: 设置弹幕透明度,透明度值在 0 到 1 之间 + + ```js + dp.danmaku.opacity(0.5); + ``` + + + `dp.danmaku.clear()`: 清除所有弹幕 + + + `dp.danmaku.hide()`: 隐藏弹幕 + + + `dp.danmaku.show()`: 显示弹幕 + ++ `dp.fullScreen`: 两个类型:`web` 和 `browser`,默认类型是 `browser` + + + `dp.fullScreen.request(type: string)`: 进入全屏 + + ```js + dp.fullScreen.request('web'); + ``` + + + `dp.fullScreen.cancel(type: string)`: 退出全屏 + + ```js + dp.fullScreen.cancel('web'); + ``` + +## 事件绑定 + +`dp.on(event, handler)` + +```js +dp.on('ended', function () { + console.log('player ended'); +}); +``` + +视频事件 + +- abort +- canplay +- canplaythrough +- durationchange +- emptied +- ended +- error +- loadeddata +- loadedmetadata +- loadstart +- mozaudioavailable +- pause +- play +- playing +- progress +- ratechange +- seeked +- seeking +- stalled +- suspend +- timeupdate +- volumechange +- waiting + +播放器事件 + +- screenshot +- thumbnails_show +- thumbnails_hide +- danmaku_show +- danmaku_hide +- danmaku_clear +- danmaku_loaded +- danmaku_send +- danmaku_opacity +- contextmenu_show +- contextmenu_hide +- notice_show +- notice_hide +- quality_start +- quality_end +- destroy +- resize +- fullscreen +- fullscreen_cancel +- subtitle_show +- subtitle_hide +- subtitle_change + +## 清晰度切换 + +在 `video.quality` 里设置不同清晰度的视频链接和类型,`video.defaultQuality` 设置默认清晰度 + + + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + quality: [{ + name: 'HD', + url: 'demo.m3u8', + type: 'hls' + }, { + name: 'SD', + url: 'demo.mp4', + type: 'normal' + }], + defaultQuality: 0, + pic: 'demo.png', + thumbnails: 'thumbnails.jpg', + } +}); +``` + +## 弹幕 + +### 弹幕接口 + +`danmaku.api` + +**现成的接口** + +链接: https://api.prprpr.me/dplayer/ + +每日备份: [DPlayer-data](https://github.com/DIYgod/DPlayer-data) + +**自己搭建** + +[DPlayer-node](https://github.com/MoePlayer/DPlayer-node) + +### bilibili 弹幕 + +`danmaku.addition` + +API: + +```js +const option = { + danmaku: { + // ... + addition: ['https://api.prprpr.me/dplayer/v3/bilibili?aid=[aid]'] + } +} +``` + +## MSE 支持 + +### HLS + +需要在 `DPlayer.min.js` 前面加载 [hls.js](https://github.com/video-dev/hls.js)。 + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.m3u8', + type: 'hls' + } +}); +``` + +```js +// 另一种方式,使用 customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.m3u8', + type: 'customHls', + customType: { + 'customHls': function (video, player) { + const hls = new Hls(); + hls.loadSource(video.src); + hls.attachMedia(video); + } + } + } +}); +``` + +### MPEG DASH + +需要在 `DPlayer.min.js` 前面加载 [dash.js](https://github.com/Dash-Industry-Forum/dash.js)。 + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.mpd', + type: 'dash' + } +}); +``` + +```js +// 另一种方式,使用 customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.mpd', + type: 'customDash', + customType: { + 'customDash': function (video, player) { + dashjs.MediaPlayer().create().initialize(video, video.src, false); + } + } + } +}); +``` + +### MPEG DASH (Shaka) + +需要在 `DPlayer.min.js` 前面加载 [shaka-player.compiled.js](https://github.com/google/shaka-player)。 + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + screenshot: true, + video: { + url: 'demo.mpd', + type: 'shakaDash', + customType: { + 'shakaDash': function (video, player) { + var src = video.src; + var playerShaka = new shaka.Player(video); // 将会修改 video.src + playerShaka.load(src); + } + } + } +}); +``` + +### FLV + +需要在 `DPlayer.min.js` 前面加载 [flv.js](https://github.com/Bilibili/flv.js)。 + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.flv', + type: 'flv' + } +}); +``` + +```js +// 另一种方式,使用 customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'demo.flv', + type: 'customFlv', + customType: { + 'customFlv': function (video, player) { + const flvPlayer = flvjs.createPlayer({ + type: 'flv', + url: video.src + }); + flvPlayer.attachMediaElement(video); + flvPlayer.load(); + } + } + } +}); +``` + +### WebTorrent + +需要在 `DPlayer.min.js` 前面加载 [webtorrent](https://github.com/webtorrent/webtorrent)。 + + + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'magnet:demo', + type: 'webtorrent' + } +}); +``` + +```js +// 另一种方式,使用 customType +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'magnet:demo', + type: 'customWebTorrent', + customType: { + 'customWebTorrent': function (video, player) { + player.container.classList.add('dplayer-loading'); + const client = new WebTorrent(); + const torrentId = video.src; + client.add(torrentId, (torrent) => { + const file = torrent.files.find((file) => file.name.endsWith('.mp4')); + file.renderTo(video, { + autoplay: player.options.autoplay + }, () => { + player.container.classList.remove('dplayer-loading'); + }); + }); + } + } + } +}); +``` + +### 配合其他 MSE 库使用 + +DPlayer 可以通过 `customType` 参数与任何 MSE 库一起使用 + +```html + +
+ + +``` + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + video: { + url: 'https://qq.webrtc.win/tv/Pear-Demo-Yosemite_National_Park.mp4', + type: 'pearplayer', + customType: { + 'pearplayer': function (video, player) { + new PearPlayer(video, { + src: video.src, + autoplay: player.options.autoplay + }); + } + } + } +}); +``` + +## 直播 + +你可以把 DPlayer 用在直播当中,但如果你想要直播弹幕,你需要自己准备一个 WebSocket 后端。 + + + +初始化播放器: + +```js +const dp = new DPlayer({ + container: document.getElementById('dplayer'), + live: true, + danmaku: true, + apiBackend: { + read: function (endpoint, callback) { + console.log('Pretend to connect WebSocket'); + callback(); + }, + send: function (endpoint, danmakuData, callback) { + console.log('Pretend to send danamku via WebSocket', danmakuData); + callback(); + } + }, + video: { + url: 'demo.m3u8', + type: 'hls' + } +}); +``` + +通过 WebSocket 获取到弹幕之后,通过 `dp.danmaku.draw` 绘制弹幕: + +```js +const danmaku = { + text: 'Get a danamku via WebSocket', + color: '#fff', + type: 'right' +}; +dp.danmaku.draw(danmaku); +``` + +## 常见问题 + +### 为什么播放器不能全屏? + +如果播放器被包含在 iframe 里,尝试在 iframe 上添加 `allowfullscreen` 属性。 + +为了完善的浏览器兼容性,它应该是这样: + +```html + +``` + +### 为什么播放器不能在手机上自动播放? + +大多数移动端浏览器禁止了视频自动播放。