浏览代码

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
                     err
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
 import { SpeedyMedia } from 'speedy-vision/types/core/speedy-media';
24
 import { SpeedyMedia } from 'speedy-vision/types/core/speedy-media';
25
 import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
25
 import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
26
 import { Utils, Nullable } from '../utils/utils';
26
 import { Utils, Nullable } from '../utils/utils';
27
-import { IllegalOperationError } from '../utils/errors';
27
+import { IllegalOperationError, NotSupportedError } from '../utils/errors';
28
 import { Source } from './source';
28
 import { Source } from './source';
29
 
29
 
30
 
30
 
94
      */
94
      */
95
     _init(): SpeedyPromise<void>
95
     _init(): SpeedyPromise<void>
96
     {
96
     {
97
-        this._handleBrowserPolicies(this._video);
97
+        this._handleBrowserQuirks(this._video);
98
 
98
 
99
         return Speedy.load(this._video).then(media => {
99
         return Speedy.load(this._video).then(media => {
100
             Utils.log(`Source of data is a ${media.width}x${media.height} ${this._type}`);
100
             Utils.log(`Source of data is a ${media.width}x${media.height} ${this._type}`);
117
     }
117
     }
118
 
118
 
119
     /**
119
     /**
120
-     * Handle browser-specific policies for <video> elements
120
+     * Handle browser-specific quirks for <video> elements
121
      * @param video
121
      * @param video
122
      * @internal
122
      * @internal
123
      */
123
      */
124
-    _handleBrowserPolicies(video: HTMLVideoElement): void
124
+    _handleBrowserQuirks(video: HTMLVideoElement): void
125
     {
125
     {
126
         // WebKit <video> policies for iOS:
126
         // WebKit <video> policies for iOS:
127
         // https://webkit.org/blog/6784/new-video-policies-for-ios/
127
         // https://webkit.org/blog/6784/new-video-policies-for-ios/
129
         // required on iOS; nice to have in all browsers
129
         // required on iOS; nice to have in all browsers
130
         video.setAttribute('playsinline', '');
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
         // note: navigator.vendor is deprecated. Alternatively, test GL_RENDERER == "Apple GPU"
137
         // note: navigator.vendor is deprecated. Alternatively, test GL_RENDERER == "Apple GPU"
154
         if(Utils.isIOS() || /Apple/.test(navigator.vendor)) {
138
         if(Utils.isIOS() || /Apple/.test(navigator.vendor)) {
155
 
139
 
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
 }

正在加载...
取消
保存