ravnur-player-public 3.4.2 → 3.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.js +206 -0
  3. package/.flowconfig +3 -0
  4. package/.vscode/extensions.json +7 -0
  5. package/.vscode/launch.json +37 -0
  6. package/.vscode/settings.json +4 -0
  7. package/README-Private.md +54 -0
  8. package/babel.config.js +28 -0
  9. package/bitbucket-pipelines.yml +61 -0
  10. package/cert.pem +23 -0
  11. package/demo/BaseM.mp4 +0 -0
  12. package/demo/HD.mp4 +0 -0
  13. package/demo/annotations.json +50 -0
  14. package/demo/annotations_ge.json +50 -0
  15. package/demo/base.mp3 +0 -0
  16. package/demo/cc_2125en.vtt +4958 -0
  17. package/demo/cc_en.vtt +171 -0
  18. package/demo/cc_ge.vtt +178 -0
  19. package/demo/chapters_en.vtt +38 -0
  20. package/demo/chapters_ge.vtt +5 -0
  21. package/demo/chapters_ge1.json +23 -0
  22. package/demo/hls/audio/stereo/en/128kbit.m3u8 +912 -0
  23. package/demo/hls/audio/stereo/none/128kbit.m3u8 +912 -0
  24. package/demo/hls/audio/surround/en/320kbit.m3u8 +912 -0
  25. package/demo/hls/playlist.m3u8 +31 -0
  26. package/demo/hls/video/10000kbit.m3u8 +894 -0
  27. package/demo/hls/video/1100kbit.m3u8 +894 -0
  28. package/demo/hls/video/1500kbit.m3u8 +894 -0
  29. package/demo/hls/video/250kbit.m3u8 +894 -0
  30. package/demo/hls/video/4000kbit.m3u8 +894 -0
  31. package/demo/hls/video/500kbit.m3u8 +894 -0
  32. package/demo/hls/video/6000kbit.m3u8 +894 -0
  33. package/demo/hls/video/800kbit.m3u8 +894 -0
  34. package/demo/hls.js +5 -0
  35. package/demo/hls.js.map +1 -0
  36. package/demo/hls.min.js +2 -0
  37. package/demo/hls.min.js.map +1 -0
  38. package/demo/playlist.m3u8 +31 -0
  39. package/demo/ravnur-flash-audio.swf +0 -0
  40. package/demo/ravnur-flash-video-hls.swf +0 -0
  41. package/demo/ravnur-flash-video.swf +0 -0
  42. package/demo/shaka/shaka-player.foo.debug.d.ts +4532 -0
  43. package/demo/shaka/shaka-player.foo.debug.externs.js +3886 -0
  44. package/demo/shaka/shaka-player.foo.debug.js +1746 -0
  45. package/demo/shaka/shaka-player.foo.debug.map +8 -0
  46. package/demo/shaka/wrapper.js +7 -0
  47. package/demo/test.html +458 -0
  48. package/dist/RavnurMediaPlayer.min.js +1 -1
  49. package/dist/cdn/RavnurMediaPlayer.min.js +1 -1
  50. package/jest.config.js +4 -0
  51. package/key.pem +27 -0
  52. package/lib/es5.js +344 -0
  53. package/lib/images/Spinner-small.gif +0 -0
  54. package/lib/images/close.png +0 -0
  55. package/lib/images/ic_check_box_black_24dp_1x.png +0 -0
  56. package/lib/images/ic_check_box_outline_blank_black_24dp_1x.png +0 -0
  57. package/lib/images/ic_chevron_left_white_24dp_1x.png +0 -0
  58. package/lib/images/ic_chevron_right_white_24dp_1x.png +0 -0
  59. package/lib/images/ic_closed_caption_white_24dp_1x.png +0 -0
  60. package/lib/images/ic_fast_forward_white_24dp_1x.png +0 -0
  61. package/lib/images/ic_fast_rewind_white_24dp_1x.png +0 -0
  62. package/lib/images/ic_fullscreen_exit_white_24dp_1x.png +0 -0
  63. package/lib/images/ic_fullscreen_white_24dp_1x.png +0 -0
  64. package/lib/images/ic_hd_white_24dp_1x.png +0 -0
  65. package/lib/images/ic_keyboard_arrow_left_black_24dp_1x.png +0 -0
  66. package/lib/images/ic_keyboard_arrow_right_black_24dp_1x.png +0 -0
  67. package/lib/images/ic_pause_white_24dp_1x.png +0 -0
  68. package/lib/images/ic_photo_white_24dp_1x.png +0 -0
  69. package/lib/images/ic_play_arrow_white_24dp_1x.png +0 -0
  70. package/lib/images/ic_refresh_white_24dp_1x.png +0 -0
  71. package/lib/images/ic_settings_white_24dp_1x.png +0 -0
  72. package/lib/images/ic_skip_next_white_24dp_1x.png +0 -0
  73. package/lib/images/ic_skip_previous_white_24dp_1x.png +0 -0
  74. package/lib/images/ic_toc_white_24dp_1x.png +0 -0
  75. package/lib/images/ic_volume_off_white_24dp_1x.png +0 -0
  76. package/lib/images/ic_volume_up_white_24dp_1x.png +0 -0
  77. package/lib/player4ie8.css +225 -0
  78. package/package.json +1 -5
  79. package/server.js +29 -0
  80. package/src/config/cc.js +56 -0
  81. package/src/config/i18n.js +101 -0
  82. package/src/config/options.js +123 -0
  83. package/src/config/playlist.js +9 -0
  84. package/src/config/source.js +23 -0
  85. package/src/config/statuses.js +8 -0
  86. package/src/config/styles.js +16 -0
  87. package/src/entity.js +27 -0
  88. package/src/events.js +5 -0
  89. package/src/extensions/annotations.js +142 -0
  90. package/src/extensions/audio-tarcks.js +115 -0
  91. package/src/extensions/backward.js +45 -0
  92. package/src/extensions/base.js +73 -0
  93. package/src/extensions/bottom-next.js +50 -0
  94. package/src/extensions/bottom-prev.js +50 -0
  95. package/src/extensions/buffering.js +78 -0
  96. package/src/extensions/c2pa.js +350 -0
  97. package/src/extensions/caption-search.js +230 -0
  98. package/src/extensions/cc.js +874 -0
  99. package/src/extensions/crawl.js +118 -0
  100. package/src/extensions/download.js +411 -0
  101. package/src/extensions/error.js +47 -0
  102. package/src/extensions/forward.js +44 -0
  103. package/src/extensions/fullscreen.js +84 -0
  104. package/src/extensions/help.js +201 -0
  105. package/src/extensions/helpers/FileSaver.js +157 -0
  106. package/src/extensions/helpers/clickOpener.js +180 -0
  107. package/src/extensions/helpers/opener.js +30 -0
  108. package/src/extensions/helpers/openerHeightChecker.js +13 -0
  109. package/src/extensions/helpers/popover.js +33 -0
  110. package/src/extensions/helpers/popoverPosition.js +30 -0
  111. package/src/extensions/helpers/scrollIntoView.js +9 -0
  112. package/src/extensions/helpers/storage.js +20 -0
  113. package/src/extensions/helpers/textContent.js +6 -0
  114. package/src/extensions/helpers/timeCodeToSeconds.js +44 -0
  115. package/src/extensions/helpers/transport.js +43 -0
  116. package/src/extensions/helpers/vtt-loader.js +42 -0
  117. package/src/extensions/index.js +87 -0
  118. package/src/extensions/live.js +76 -0
  119. package/src/extensions/mux.js +57 -0
  120. package/src/extensions/next-frame.js +44 -0
  121. package/src/extensions/next.js +48 -0
  122. package/src/extensions/placeholder.js +241 -0
  123. package/src/extensions/play.js +102 -0
  124. package/src/extensions/poster.js +47 -0
  125. package/src/extensions/prev-frame.js +44 -0
  126. package/src/extensions/prev.js +48 -0
  127. package/src/extensions/progress.js +465 -0
  128. package/src/extensions/resizer.js +37 -0
  129. package/src/extensions/settings.js +367 -0
  130. package/src/extensions/theater.js +56 -0
  131. package/src/extensions/title.js +38 -0
  132. package/src/extensions/toc.js +334 -0
  133. package/src/extensions/volume.js +196 -0
  134. package/src/flash/FlashPlugin.js +301 -0
  135. package/src/flash/MediaElement.js +361 -0
  136. package/src/flash/plugins.js +32 -0
  137. package/src/flash-detector.js +66 -0
  138. package/src/helpers/$t.js +10 -0
  139. package/src/helpers/binder.js +11 -0
  140. package/src/helpers/isAndroid.js +5 -0
  141. package/src/helpers/isBlackBerry.js +5 -0
  142. package/src/helpers/isCanvasSupported.js +6 -0
  143. package/src/helpers/isIE.js +21 -0
  144. package/src/helpers/isMobile.js +10 -0
  145. package/src/helpers/isWindows.js +5 -0
  146. package/src/helpers/isWindowsPhone.js +5 -0
  147. package/src/helpers/isiOS.js +5 -0
  148. package/src/html5media.js +19 -0
  149. package/src/index.js +2 -0
  150. package/src/logger.js +31 -0
  151. package/src/microevent.js +65 -0
  152. package/src/normalize-options.js +139 -0
  153. package/src/player.js +864 -0
  154. package/src/players/base.js +209 -0
  155. package/src/players/flash.js +172 -0
  156. package/src/players/hls.js +278 -0
  157. package/src/players/html.js +205 -0
  158. package/src/players/index.js +59 -0
  159. package/src/players/shaka.js +219 -0
  160. package/src/playlist.js +362 -0
  161. package/src/screenfull.js +121 -0
  162. package/src/state.js +474 -0
  163. package/src/static/es5.js +344 -0
  164. package/src/static/images/Spinner-small.gif +0 -0
  165. package/src/static/images/close.png +0 -0
  166. package/src/static/images/ic_check_box_black_24dp_1x.png +0 -0
  167. package/src/static/images/ic_check_box_outline_blank_black_24dp_1x.png +0 -0
  168. package/src/static/images/ic_chevron_left_white_24dp_1x.png +0 -0
  169. package/src/static/images/ic_chevron_right_white_24dp_1x.png +0 -0
  170. package/src/static/images/ic_closed_caption_white_24dp_1x.png +0 -0
  171. package/src/static/images/ic_fast_forward_white_24dp_1x.png +0 -0
  172. package/src/static/images/ic_fast_rewind_white_24dp_1x.png +0 -0
  173. package/src/static/images/ic_fullscreen_exit_white_24dp_1x.png +0 -0
  174. package/src/static/images/ic_fullscreen_white_24dp_1x.png +0 -0
  175. package/src/static/images/ic_hd_white_24dp_1x.png +0 -0
  176. package/src/static/images/ic_keyboard_arrow_left_black_24dp_1x.png +0 -0
  177. package/src/static/images/ic_keyboard_arrow_right_black_24dp_1x.png +0 -0
  178. package/src/static/images/ic_pause_white_24dp_1x.png +0 -0
  179. package/src/static/images/ic_play_arrow_white_24dp_1x.png +0 -0
  180. package/src/static/images/ic_refresh_white_24dp_1x.png +0 -0
  181. package/src/static/images/ic_settings_white_24dp_1x.png +0 -0
  182. package/src/static/images/ic_skip_next_white_24dp_1x.png +0 -0
  183. package/src/static/images/ic_skip_previous_white_24dp_1x.png +0 -0
  184. package/src/static/images/ic_toc_white_24dp_1x.png +0 -0
  185. package/src/static/images/ic_volume_off_white_24dp_1x.png +0 -0
  186. package/src/static/images/ic_volume_up_white_24dp_1x.png +0 -0
  187. package/src/static/player4ie8.css +225 -0
  188. package/src/styles/bplaylist.css.js +124 -0
  189. package/src/styles/index.js +1966 -0
  190. package/src/styles/playlist.css.js +84 -0
  191. package/src/styles/rplaylist.css.js +98 -0
  192. package/src/svgs.js +111 -0
  193. package/src/types/Logger.js +10 -0
  194. package/src/types/Options.js +179 -0
  195. package/src/types/Playlist.js +3 -0
  196. package/src/types/Source.js +28 -0
  197. package/src/types/State.js +46 -0
  198. package/src/types/Styles.js +11 -0
  199. package/src/types/TimeData.js +8 -0
  200. package/src/types/Translation.js +69 -0
  201. package/src/utils/absolutizeUrl.js +9 -0
  202. package/src/utils/addClass.js +9 -0
  203. package/src/utils/addEvent.js +31 -0
  204. package/src/utils/addProperty.js +65 -0
  205. package/src/utils/appendChild.js +14 -0
  206. package/src/utils/buff2hex.js +5 -0
  207. package/src/utils/contains.js +33 -0
  208. package/src/utils/createElement.js +24 -0
  209. package/src/utils/each.js +34 -0
  210. package/src/utils/escapeHTML.js +8 -0
  211. package/src/utils/existy.js +4 -0
  212. package/src/utils/extend.js +17 -0
  213. package/src/utils/filter.js +16 -0
  214. package/src/utils/find.js +11 -0
  215. package/src/utils/findIndex.js +20 -0
  216. package/src/utils/first.js +5 -0
  217. package/src/utils/get.js +19 -0
  218. package/src/utils/has.js +5 -0
  219. package/src/utils/hasClass.js +6 -0
  220. package/src/utils/head.js +11 -0
  221. package/src/utils/inRange.js +16 -0
  222. package/src/utils/index.js +73 -0
  223. package/src/utils/isArray.js +4 -0
  224. package/src/utils/isBoolean.js +3 -0
  225. package/src/utils/isElement.js +7 -0
  226. package/src/utils/isEmpty.js +6 -0
  227. package/src/utils/isEqual.js +33 -0
  228. package/src/utils/isEqualBuffer.js +13 -0
  229. package/src/utils/isFunction.js +3 -0
  230. package/src/utils/isNotEmpty.js +5 -0
  231. package/src/utils/isObject.js +5 -0
  232. package/src/utils/isString.js +9 -0
  233. package/src/utils/last.js +4 -0
  234. package/src/utils/map.js +11 -0
  235. package/src/utils/negate.js +8 -0
  236. package/src/utils/noop.js +1 -0
  237. package/src/utils/notExisty.js +5 -0
  238. package/src/utils/reduce.js +8 -0
  239. package/src/utils/remove.js +7 -0
  240. package/src/utils/removeClass.js +8 -0
  241. package/src/utils/removeEvent.js +7 -0
  242. package/src/utils/toArray.js +7 -0
  243. package/src/utils/toggleClass.js +16 -0
  244. package/src/utils/uidGenerator.js +8 -0
  245. package/src/utils/upperFirst.js +4 -0
  246. package/tests/extensions/__snapshots__/download.spec.js.snap +226 -0
  247. package/tests/extensions/__snapshots__/fullscreen.spec.js.snap +30 -0
  248. package/tests/extensions/__snapshots__/title.spec.js.snap +16 -0
  249. package/tests/extensions/download.spec.js +111 -0
  250. package/tests/extensions/fullscreen.spec.js +56 -0
  251. package/tests/extensions/title.spec.js +35 -0
  252. package/tests/mocks/assets/BaseM.mp4 +0 -0
  253. package/tests/mocks/assets/hls.min.js +5 -0
  254. package/tests/mocks/assets/styleMock.js +1 -0
  255. package/tests/mocks/base-player-options.js +47 -0
  256. package/tests/mocks/sources.js +58 -0
  257. package/tests/mocks/timedata/cc_en.vtt +171 -0
  258. package/tests/mocks/timedata/cc_ge.vtt +178 -0
  259. package/tests/utils/wait.js +1 -0
  260. package/webpack.config.js +78 -0
  261. package/dist/.DS_Store +0 -0
  262. package/dist/cdn/.DS_Store +0 -0
@@ -0,0 +1,205 @@
1
+ import BasePlayer from './base';
2
+
3
+ import events from '../events';
4
+
5
+ import { createElement, append, each, find, first, isArray, uidGenerator, findIndex } from '../utils';
6
+ import isIOS from '../helpers/isiOS';
7
+ import {
8
+ UNTRANSLATED_TIMEDATA_STATUS
9
+ } from '../config/statuses';
10
+
11
+ export default class HtmlPlayer extends BasePlayer {
12
+ $el;
13
+ source;
14
+ _levels = [];
15
+ _currentLevel = null;
16
+
17
+ constructor(options, state) {
18
+ super(options, state);
19
+ this.logger.debug('html:player:creating');
20
+
21
+ let tag = 'video';
22
+ const params = { id: uidGenerator(), tabindex: -1 };
23
+
24
+ if ( options.disableAutoFullScreenOnIOS ) {
25
+ params['webkit-playsinline'] = true;
26
+ params.playsinline = true;
27
+ }
28
+
29
+ if ( options.isMobile ) {
30
+ params.preload = 'metadata';
31
+ // use audio for audio. fix for ios safari RAV-2462
32
+ tag = options.isAudio ? 'audio' : 'video';
33
+ }
34
+
35
+ /** @type {HTMLMediaElement} */
36
+ // use video also for audio. fix for opera. RAV-412
37
+ this.$el = createElement(tag, params);
38
+
39
+ each(events, type => {
40
+ this.addEvent(this.$el, type, event => {
41
+ this.logger.debug('triggered event', type);
42
+ this.bus.emit(type, event);
43
+ });
44
+ });
45
+
46
+ this.handleFullscreenChanging = this.handleFullscreenChanging.bind(this);
47
+ this.handleWebkitEndFullscreen = this.handleWebkitEndFullscreen.bind(this);
48
+
49
+ if (isIOS()) {
50
+ this.bus.on('fullscreenchanging', this.handleFullscreenChanging);
51
+ }
52
+ this.logger.debug('html:player:created');
53
+ }
54
+
55
+ load({type, src, cc}) {
56
+ let options = { type, src };
57
+ // i hate opera, safari, iOS
58
+ if (this.options.isMobile && type === 'audio/mp3') {
59
+ options = { src };
60
+ }
61
+ if ( isArray(src) ) {
62
+ this._levels = src;
63
+ if (this.options.qualityLevel) {
64
+ const h = parseInt(this.options.qualityLevel, 10);
65
+ if (h) {
66
+ this._currentLevel = find(this._levels, l => parseInt(l.name, 10) === h);
67
+ }
68
+ }
69
+ this._currentLevel = this._currentLevel || find(this._levels, lvl => lvl.default);
70
+ this._currentLevel = this._currentLevel || first(this._levels);
71
+ options.src = this._currentLevel.src;
72
+ }
73
+
74
+ this.logger.debug('html:player:loading', src);
75
+ this.source = createElement('source', options);
76
+
77
+ this.source.addEventListener('error', (e) => {
78
+ this.bus.emit('error', e);
79
+ this.logger.error(e);
80
+ });
81
+
82
+ append(this.$el, this.source);
83
+
84
+ if (isIOS()) {
85
+ each(cc, (track) => {
86
+ if (track.state !== UNTRANSLATED_TIMEDATA_STATUS && track.type !== 'json') {
87
+ append(this.$el, createElement('track', track));
88
+ }
89
+ });
90
+ }
91
+
92
+ if (this.$el.audioTracks) {
93
+ this.$el.audioTracks.onchange = () => {
94
+ this.bus.emit('audiotrackswitched');
95
+ };
96
+ }
97
+
98
+ this.$el.addEventListener('webkitendfullscreen', this.handleWebkitEndFullscreen);
99
+ if (isIOS()) {
100
+ this.bus.once('loadeddata', () => {
101
+ const textTracks = this.getTextTracks();
102
+ if (textTracks instanceof TextTrackList) {
103
+ textTracks.addEventListener('change', () => {
104
+ const tt = find(textTracks, (tt) => tt.mode === 'showing');
105
+ if (tt) {
106
+ this.bus.emit('cclang', tt.language);
107
+ }
108
+ });
109
+ }
110
+ this.handleWebkitEndFullscreen();
111
+ });
112
+ }
113
+ }
114
+
115
+ getLevels() {
116
+ return this._levels;
117
+ }
118
+
119
+ setLevel(level) {
120
+ const currentTime = this.$el.currentTime;
121
+ const paused = this.$el.paused;
122
+ this._currentLevel = level;
123
+ this.$el.pause();
124
+ this.source.src = level.src;
125
+
126
+ this.bus.once('loadedmetadata', () => {
127
+ this.$el.currentTime = currentTime;
128
+
129
+ if (!paused) {
130
+ this.$el.play();
131
+ }
132
+
133
+ });
134
+ this.$el.currentTime = currentTime;
135
+ this.$el.load();
136
+ }
137
+
138
+ setPlaybackRate(rate) {
139
+ this.$el.playbackRate = rate;
140
+ this.$el.defaultPlaybackRate = rate;
141
+ }
142
+
143
+ getLevel() {
144
+ return this._currentLevel;
145
+ }
146
+
147
+ getElement() {
148
+ return this.$el;
149
+ }
150
+
151
+ getBufferedPercent() {
152
+ const target = this.$el;
153
+ if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) {
154
+ return target.buffered.end(target.buffered.length - 1) / target.duration;
155
+ }
156
+
157
+ return 0;
158
+ }
159
+
160
+ getAudioTrack() {
161
+ return findIndex(this.getAudioTracks(), (track) => track.enabled);
162
+ }
163
+
164
+ getAudioTracks() {
165
+ return this.$el.audioTracks || [];
166
+ }
167
+
168
+ setAudioTrack(idx) {
169
+ each(this.getAudioTracks(), (track, index) => {
170
+ if (track && typeof track === 'object') {
171
+ track.enabled = index == idx;
172
+ }
173
+ });
174
+ }
175
+
176
+ getTextTracks() {
177
+ return this.$el.textTracks || [];
178
+ }
179
+
180
+ handleFullscreenChanging(flag) {
181
+ const lang = flag !== true ? this.state.getCCLang() : '__';
182
+ this._textTrackWalker((track) => track.language === lang ? 'showing' : 'disabled');
183
+ }
184
+
185
+ handleWebkitEndFullscreen() {
186
+ this.handleFullscreenChanging(this.$el.webkitDisplayingFullscreen);
187
+ }
188
+
189
+ _textTrackWalker(modeFiller) {
190
+ each(this.getTextTracks(), (track) => {
191
+ if (track && typeof track === 'object') {
192
+ track.mode = modeFiller(track);
193
+ }
194
+ });
195
+ }
196
+
197
+ destroy() {
198
+ this.$el.removeEventListener('webkitendfullscreen', this.handleWebkitEndFullscreen);
199
+ this.bus.off('fullscreenchanging', this.handleFullscreenChanging);
200
+ super.destroy();
201
+ this.$el.parentNode.removeChild(this.$el);
202
+ this.$el = null;
203
+ this.source = null;
204
+ }
205
+ }
@@ -0,0 +1,59 @@
1
+ // @flow
2
+ import HtmlPlayer from './html';
3
+ import HLSPlayer from './hls';
4
+ import FlashPlayer from './flash';
5
+ import ShakaPlayer from './shaka';
6
+
7
+ import {
8
+ existy,
9
+ isFunction,
10
+ contains
11
+ } from '../utils';
12
+
13
+ import type { Player$CombineOptions } from '../types/Options';
14
+
15
+ const CODEC = 'video/mp4; codecs=avc1.42E01E,mp4a.40.2';
16
+ const HLS_TYPES = [ 'application/x-mpegURL', 'vnd.apple.mpegURL', 'application/vnd.apple.mpegurl' ];
17
+
18
+ export const HLS_TYPE = 'HLS';
19
+ export const FLASH_TYPE = 'Flash';
20
+ export const HTML5_TYPE = 'HTML5';
21
+ export const SHAKA_TYPE = 'Shaka';
22
+
23
+ const MAP = {};
24
+ MAP[HLS_TYPE] = HLSPlayer;
25
+ MAP[FLASH_TYPE] = FlashPlayer;
26
+ MAP[HTML5_TYPE] = HtmlPlayer;
27
+ MAP[SHAKA_TYPE] = ShakaPlayer;
28
+
29
+ export default function createInstance(options: $Shape<Player$CombineOptions>, state) {
30
+ const type = getPlayerType(options);
31
+ const Player = MAP[type];
32
+ return new Player(options, state);
33
+ }
34
+
35
+ export function getPlayerType(opts: $Shape<Player$CombineOptions>) {
36
+ const {type, logger} = opts;
37
+
38
+ if (opts.useHTMLPlayer) {
39
+ logger.debug('Using html player for type: ', type);
40
+ return HTML5_TYPE;
41
+ }
42
+
43
+ if (_canUseMediaSource() && (opts.useHLSJSPlayer || opts.isLive)) {
44
+ logger.debug('Using hlsjs player for type: ', type);
45
+ return HLS_TYPE;
46
+ }
47
+
48
+ logger.debug('Using shaka player for type: ', type);
49
+ return SHAKA_TYPE;
50
+ }
51
+
52
+ export function isHLS(type: string) {
53
+ return contains(HLS_TYPES, type);
54
+ }
55
+
56
+ function _canUseMediaSource() {
57
+ const ms = window.ManagedMediaSource || window.MediaSource || window.WebKitMediaSource;
58
+ return existy(ms) && isFunction(ms.isTypeSupported) && ms.isTypeSupported(CODEC);
59
+ }
@@ -0,0 +1,219 @@
1
+ import isiOS from '../helpers/isiOS';
2
+ import {
3
+ first,
4
+ createElement,
5
+ isArray,
6
+ isObject,
7
+ head
8
+ } from '../utils';
9
+ import HtmlPlayer from './html';
10
+
11
+ const AUTO_LEVEL = { name: 'Auto' };
12
+
13
+ export default class ShakaPlayer extends HtmlPlayer {
14
+ constructor(options, state) {
15
+ super(options, state);
16
+ this.logger.debug('shaka:player:created');
17
+ }
18
+
19
+ load({ src, type }) {
20
+ src = isArray(src) ? head(src) : src;
21
+ src = isObject(src) ? src.src : src;
22
+
23
+ // If the source is a DASH stream
24
+ // and the device is an iOS device, we need to convert it to HLS
25
+ if (/format=mpd-time-csf/.test(src) && isiOS() && !this.options.disableAutoUrlRewrite) {
26
+ type = 'application/x-mpegurl';
27
+ src = src.replace('format=mpd-time-csf', 'format=m3u8-cmaf');
28
+ }
29
+
30
+ this.onError = this.onError.bind(this);
31
+
32
+ this.logger.debug('shaka:player:loading', src);
33
+ this._loadLibraryAndAttachMedia(src, type);
34
+ }
35
+
36
+ _loadLibraryAndAttachMedia(src, type) {
37
+ // use requiresjs if we can
38
+ if (typeof window.define === 'function' && window.define.amd) {
39
+ window.require.config({
40
+ paths: {
41
+ shakajs: this.options.shakaURL
42
+ }
43
+ });
44
+
45
+ window.require(['shakajs'], shaka => {
46
+ window.shaka = shaka;
47
+ this._attachMedia(src, type);
48
+ });
49
+ } else {
50
+ const script = createElement('script', { src: this.options.shakaURL });
51
+ const firstScriptTag = first(document.getElementsByTagName('script'));
52
+ script.onload = script.onreadystatechange = () => this._attachMedia(src, type);
53
+
54
+ if (!firstScriptTag.parentNode) return;
55
+
56
+ firstScriptTag.parentNode.insertBefore(script, firstScriptTag);
57
+ }
58
+ }
59
+
60
+ async _attachMedia(src, type) {
61
+ let shakaOptions = this.options.shaka;
62
+ window.shaka.polyfill.installAll();
63
+
64
+ if (window.shaka.Player.isBrowserSupported()) {
65
+ this.shaka = new window.shaka.Player();
66
+
67
+ if (this.options.shaka) {
68
+ this.shaka.configure(this.options.shaka);
69
+ }
70
+
71
+ this.shaka.setTextTrackVisibility(!!this.options.showSubtitles);
72
+
73
+ this.preselectQuality();
74
+ this.modifyRequests(src);
75
+
76
+ if (this.options.maxQualityLevel) {
77
+ this.limitLevel(this.options.maxQualityLevel);
78
+ }
79
+
80
+ await this.configureDRM();
81
+ await this.shaka.attach(this.$el);
82
+
83
+ // See: https://github.com/shaka-project/shaka-player/issues/9415
84
+ // Can be removed after Shaka v5 release and Ravnur Player update to Shaka v5
85
+ const normolizedMimeType = type.toLowerCase();
86
+
87
+ await this.shaka.load(src, null, normolizedMimeType).catch(this.onError);
88
+
89
+ // Catching errors after load
90
+ const listener = new window.shaka.util.EventManager();
91
+ listener.listen(this.shaka, 'error', (e) => this.onError(e.detail));
92
+
93
+ this.shaka.configure(shakaOptions);
94
+ } else {
95
+ this.logger.error('Browser not supported!');
96
+ }
97
+ }
98
+
99
+ async configureDRM() {
100
+ const servers = {};
101
+
102
+ if (this.options.widevineURL) {
103
+ servers['com.widevine.alpha'] = this.options.widevineURL;
104
+ }
105
+
106
+ if (this.options.playreadyURL) {
107
+ servers['com.microsoft.playready'] = this.options.playreadyURL;
108
+ }
109
+
110
+ if (this.options.fairplayURL) {
111
+ servers['com.apple.fps.1_0'] = this.options.fairplayURL;
112
+ }
113
+
114
+ this.shaka.configure({ drm: { servers } });
115
+
116
+ if (this.options.fairplayCertificateUrl) {
117
+ const req = await fetch(this.options.fairplayCertificateUrl);
118
+ const cert = await req.arrayBuffer();
119
+
120
+ this.shaka.configure('drm.advanced.com\\.apple\\.fps\\.1_0.serverCertificate', new Uint8Array(cert));
121
+
122
+ window.shaka.polyfill.PatchedMediaKeysApple.install();
123
+
124
+ const FairPlayUtils = window.shaka.util.FairPlayUtils;
125
+ this.shaka.getNetworkingEngine().registerRequestFilter(FairPlayUtils.ezdrmFairPlayRequest);
126
+ this.shaka.getNetworkingEngine().registerResponseFilter(FairPlayUtils.commonFairPlayResponse);
127
+ this.shaka.configure('drm.initDataTransform', FairPlayUtils.ezdrmInitDataTransform);
128
+ }
129
+ }
130
+
131
+ onError(event) {
132
+ this.bus.emit('error', event);
133
+ this.logger.error(event);
134
+ }
135
+
136
+ modifyRequests(src) {
137
+ this.shaka.getNetworkingEngine().registerRequestFilter((type, request) => {
138
+ if (type === window.shaka.net.NetworkingEngine.RequestType.KEY && this.options.aesToken) {
139
+ request.headers.Authorization = 'Bearer ' + this.options.aesToken;
140
+ }
141
+
142
+ const params = src?.split('?')[1]?.split('&');
143
+
144
+ // Append query parameters in case when token is required in the query
145
+ // check query parameters and if request uri don't contain it add it
146
+ if (params?.length) {
147
+ params.forEach((value) => {
148
+ const requestHadParams = request.uris[0]?.split('?')[1];
149
+
150
+ if (!requestHadParams) {
151
+ request.uris[0] += '?' + value;
152
+ } else if (!request.uris[0].includes(value)) {
153
+ request.uris[0] += '&' + value;
154
+ }
155
+ });
156
+ }
157
+ });
158
+ }
159
+
160
+ preselectQuality() {
161
+ if (!this.options.qualityLevel) {
162
+ return;
163
+ }
164
+
165
+ const eventManager = new window.shaka.util.EventManager();
166
+
167
+ eventManager.listen(this.shaka, 'streaming', () => {
168
+ const h = parseInt(this.options.qualityLevel, 10);
169
+ const level = this.getLevels().find(l => l.height === h);
170
+
171
+ if (level) {
172
+ this.setLevel(level);
173
+ }
174
+ });
175
+
176
+ }
177
+
178
+ getLevels() {
179
+ return [AUTO_LEVEL].concat(this.shaka.getVariantTracks());
180
+ }
181
+
182
+ setLevel(level) {
183
+ if (level === AUTO_LEVEL) {
184
+ this.shaka.configure({ abr: { enabled: true } });
185
+ } else {
186
+ this.shaka.configure({ abr: { enabled: false } });
187
+ this.shaka.selectVariantTrack(level, true);
188
+ }
189
+ }
190
+
191
+ limitLevel(level) {
192
+ const h = parseInt(level, 10);
193
+ if (h) {
194
+ this.shaka.configure({ abr: { restrictions: { maxHeight: h } } });
195
+ }
196
+ }
197
+
198
+ goToLive() {
199
+ this.shaka.goToLive();
200
+ }
201
+
202
+ isLive() {
203
+ return this.$el.currentTime >= this.shaka?.seekRange()?.end - 10;
204
+ }
205
+
206
+ getLevel() {
207
+ const track = this.shaka.getVariantTracks().find(track => track.active);
208
+ return this.shaka.getConfiguration().abr.enabled ? AUTO_LEVEL : track;
209
+ }
210
+
211
+ isMultiQuality() {
212
+ return this.shaka.getVariantTracks().length > 1;
213
+ }
214
+
215
+ destroy() {
216
+ this.shaka.destroy();
217
+ super.destroy();
218
+ }
219
+ }