瀏覽代碼

Add VideoSource._handleAutoPlay()

customisations
alemart 1 年之前
父節點
當前提交
649d782ce6
共有 2 個檔案被更改,包括 60 行新增25 行删除
  1. 1
    1
      src/sources/camera-source.ts
  2. 59
    24
      src/sources/video-source.ts

+ 1
- 1
src/sources/camera-source.ts 查看文件

@@ -130,7 +130,7 @@ export class CameraSource extends VideoSource
130 130
                     err
131 131
                 ));
132 132
             });
133
-        }).then(_ => super._init());
133
+        }).then(_ => super._init()); // this will call VideoSource._handleBrowserQuirks()
134 134
     }
135 135
 
136 136
     /**

+ 59
- 24
src/sources/video-source.ts 查看文件

@@ -24,7 +24,7 @@ import Speedy from 'speedy-vision';
24 24
 import { SpeedyMedia } from 'speedy-vision/types/core/speedy-media';
25 25
 import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
26 26
 import { Utils, Nullable } from '../utils/utils';
27
-import { IllegalOperationError } from '../utils/errors';
27
+import { IllegalOperationError, NotSupportedError } from '../utils/errors';
28 28
 import { Source } from './source';
29 29
 
30 30
 
@@ -94,7 +94,7 @@ export class VideoSource implements Source
94 94
      */
95 95
     _init(): SpeedyPromise<void>
96 96
     {
97
-        this._handleBrowserPolicies(this._video);
97
+        this._handleBrowserQuirks(this._video);
98 98
 
99 99
         return Speedy.load(this._video).then(media => {
100 100
             Utils.log(`Source of data is a ${media.width}x${media.height} ${this._type}`);
@@ -117,11 +117,11 @@ export class VideoSource implements Source
117 117
     }
118 118
 
119 119
     /**
120
-     * Handle browser-specific policies for <video> elements
120
+     * Handle browser-specific quirks for <video> elements
121 121
      * @param video
122 122
      * @internal
123 123
      */
124
-    _handleBrowserPolicies(video: HTMLVideoElement): void
124
+    _handleBrowserQuirks(video: HTMLVideoElement): void
125 125
     {
126 126
         // WebKit <video> policies for iOS:
127 127
         // https://webkit.org/blog/6784/new-video-policies-for-ios/
@@ -129,27 +129,11 @@ export class VideoSource implements Source
129 129
         // required on iOS; nice to have in all browsers
130 130
         video.setAttribute('playsinline', '');
131 131
 
132
-        // autoplay videos should be muted
133
-        if(video.autoplay) {
134
-            video.muted = true;
135
-            video.addEventListener('canplay', () => {
136
-                const p = video.play();
137
-                if(typeof p === 'object') {
138
-                    p.catch((error: DOMException) => {
139
-                        Utils.error(`Can't autoplay video!`, error, video);
140
-
141
-                        if(error.name == 'NotAllowedError') {
142
-                            Utils.warning('Tip: allow manual playback');
143
-
144
-                            if(Utils.isIOS())
145
-                                Utils.warning('Is low power mode on?');
146
-                        }
147
-                    });
148
-                }
149
-            });
150
-        }
132
+        // handle autoplay
133
+        if(video.autoplay)
134
+            this._handleAutoPlay(video);
151 135
 
152
-        // Handle WebKit policies
136
+        // Handle WebKit quirks
153 137
         // note: navigator.vendor is deprecated. Alternatively, test GL_RENDERER == "Apple GPU"
154 138
         if(Utils.isIOS() || /Apple/.test(navigator.vendor)) {
155 139
 
@@ -162,4 +146,55 @@ export class VideoSource implements Source
162 146
 
163 147
         }
164 148
     }
149
+
150
+    /**
151
+     * Handle browser-specific quirks for videos marked with autoplay
152
+     * @param video a <video> marked with autoplay
153
+     * @internal
154
+     */
155
+    _handleAutoPlay(video: HTMLVideoElement): void
156
+    {
157
+        Utils.assert(video.autoplay);
158
+
159
+        // videos marked with autoplay should be muted
160
+        video.muted = true;
161
+
162
+        // the browser may not honor the autoplay attribute if the video is not
163
+        // visible on-screen. So, let's try to play the video in any case.
164
+        video.addEventListener('canplay', () => {
165
+            const promise = video.play();
166
+
167
+            // handle older browsers
168
+            if(typeof promise !== 'object')
169
+                return;
170
+
171
+            // can't play the video
172
+            promise.catch((error: DOMException) => {
173
+                Utils.error(`Can't autoplay video!`, error, video);
174
+
175
+                // autoplay is blocked for some reason
176
+                if(error.name == 'NotAllowedError') {
177
+                    Utils.warning('Tip: allow manual playback');
178
+
179
+                    if(Utils.isIOS())
180
+                        Utils.warning('Is low power mode on?');
181
+
182
+                    // User interaction is required to play the video. We can
183
+                    // solve this here (easy and convenient to do) or at the
184
+                    // application layer (for a better user experience). If the
185
+                    // latter is preferred, just disable autoplay and play the
186
+                    // video programatically.
187
+                    if(video.hidden || !video.controls || video.parentNode === null) {
188
+                        // this is added for convenience
189
+                        document.body.addEventListener('pointerdown', () => video.play());
190
+                        alert('Tap on the screen to start');
191
+                    }
192
+                }
193
+
194
+                // unsupported media source
195
+                else if(error.name == 'NotSupportedError')
196
+                    throw new NotSupportedError('Unsupported video format', error);
197
+            });
198
+        });
199
+    }
165 200
 }

Loading…
取消
儲存