Skip to content

Commit 29b9801

Browse files
committed
Load as blob works and finished documentation.
1 parent ad8d8b0 commit 29b9801

1 file changed

Lines changed: 105 additions & 116 deletions

File tree

src/loader/filetypes/VideoFile.js

Lines changed: 105 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ var IsPlainObject = require('../../utils/object/IsPlainObject');
2929
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
3030
* @param {(string|Phaser.Types.Loader.FileTypes.VideoFileConfig)} key - The key to use for this file, or a file configuration object.
3131
* @param {any} [urlConfig] - The absolute or relative URL to load this file from in a config object.
32+
* @param {string} [loadEvent] - The load event to listen for when _not_ loading as a blob. Either 'loadeddata', 'canplay' or 'canplaythrough'.
33+
* @param {boolean} [asBlob] - Load the video as a data blob, or via the Video element?
34+
* @param {boolean} [noAudio] - Does the video have an audio track? If not you can enable auto-playing on it.
3235
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
33-
* @param {AudioContext} [audioContext] - The AudioContext this file will use to process itself.
3436
*/
3537
var VideoFile = new Class({
3638

@@ -45,6 +47,11 @@ var VideoFile = new Class({
4547
if (asBlob === undefined) { asBlob = false; }
4648
if (noAudio === undefined) { noAudio = false; }
4749

50+
if (loadEvent !== 'loadeddata' && loadEvent !== 'canplay' && loadEvent !== 'canplaythrough')
51+
{
52+
loadEvent = 'loadeddata';
53+
}
54+
4855
var fileConfig = {
4956
type: 'video',
5057
cache: loader.cacheManager.video,
@@ -60,7 +67,8 @@ var VideoFile = new Class({
6067
}
6168
};
6269

63-
// console.log(fileConfig);
70+
this.onLoadCallback = this.onVideoLoadHandler.bind(this);
71+
this.onErrorCallback = this.onVideoErrorHandler.bind(this);
6472

6573
File.call(this, loader, fileConfig);
6674
},
@@ -69,13 +77,11 @@ var VideoFile = new Class({
6977
* Called automatically by Loader.nextFile.
7078
* This method controls what extra work this File does with its loaded data.
7179
*
72-
* @method Phaser.Loader.FileTypes.BinaryFile#onProcess
73-
* @since 3.7.0
80+
* @method Phaser.Loader.FileTypes.VideoFile#onProcess
81+
* @since 3.20.0
7482
*/
7583
onProcess: function ()
7684
{
77-
// console.log('Video.onProcess', this.config.asBlob);
78-
7985
this.state = CONST.FILE_PROCESSING;
8086

8187
if (!this.config.asBlob)
@@ -85,154 +91,134 @@ var VideoFile = new Class({
8591
return;
8692
}
8793

88-
var video = document.createElement('video');
89-
90-
video.controls = false;
91-
video.canplay = true;
92-
93-
video.setAttribute('autoplay', 'autoplay');
94-
video.setAttribute('playsinline', 'playsinline');
94+
// Load Video as blob
9595

96-
if (this.config.noAudio)
97-
{
98-
video.muted = true;
99-
}
96+
var video = this.createVideoElement();
10097

10198
this.data = video;
10299

103100
var _this = this;
104101

105102
this.data.onloadeddata = function ()
106103
{
107-
// console.log('data.onloadeddata');
108-
109104
File.revokeObjectURL(_this.data);
110105

111106
_this.onProcessComplete();
112107
};
113108

114109
this.data.onerror = function ()
115110
{
116-
// console.log('data.onerror');
117-
118111
File.revokeObjectURL(_this.data);
119112

120113
_this.onProcessError();
121114
};
122115

123-
// console.log('onProcess createURL');
116+
File.createObjectURL(video, this.xhrLoader.response, '');
117+
118+
video.load();
119+
},
120+
121+
/**
122+
* Creates a Video Element within the DOM.
123+
*
124+
* @method Phaser.Loader.FileTypes.VideoFile#createVideoElement
125+
* @private
126+
* @since 3.20.0
127+
*
128+
* @return {HTMLVideoElement} The newly created Video element.
129+
*/
130+
createVideoElement: function ()
131+
{
132+
var video = document.createElement('video');
133+
134+
video.controls = false;
135+
video.crossOrigin = this.loader.crossOrigin;
136+
137+
if (this.config.noAudio)
138+
{
139+
video.muted = true;
140+
video.defaultMuted = true;
141+
142+
video.setAttribute('autoplay', 'autoplay');
143+
}
144+
145+
video.setAttribute('playsinline', 'playsinline');
146+
video.setAttribute('preload', 'auto');
124147

125-
File.createObjectURL(this.data, this.xhrLoader.response, '');
148+
return video;
126149
},
127150

128151
/**
129-
* Called when the file finishes loading, is sent a DOM ProgressEvent.
152+
* Internal load event callback.
130153
*
131-
* @method Phaser.Loader.File#onLoad
132-
* @since 3.0.0
154+
* @method Phaser.Loader.FileTypes.VideoFile#onVideoLoadHandler
155+
* @private
156+
* @since 3.20.0
133157
*
134-
* @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event.
135158
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this load.
136-
onLoadVideo: function (event)
159+
*/
160+
onVideoLoadHandler: function (event)
137161
{
138-
console.log('onLoadVideo');
139-
console.log(event);
140-
console.log(this);
141-
142162
var video = event.target;
143163

144-
video.removeEventListener(this.config.loadEvent, this.onLoadVideo, true);
164+
video.removeEventListener(this.config.loadEvent, this.onLoadCallback, true);
165+
video.removeEventListener('error', this.onErrorCallback, true);
145166

146167
this.data = video;
147168

148169
this.resetXHR();
149170

150171
this.loader.nextFile(this, true);
151172
},
173+
174+
/**
175+
* Internal load error event callback.
176+
*
177+
* @method Phaser.Loader.FileTypes.VideoFile#onVideoErrorHandler
178+
* @private
179+
* @since 3.20.0
180+
*
181+
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this load.
152182
*/
183+
onVideoErrorHandler: function (event)
184+
{
185+
var video = event.target;
186+
187+
if (video)
188+
{
189+
video.removeEventListener(this.config.loadEvent, this.onLoadCallback, true);
190+
video.removeEventListener('error', this.onErrorCallback, true);
191+
}
192+
193+
this.resetXHR();
194+
195+
this.loader.nextFile(this, false);
196+
},
153197

154198
/**
155199
* Called by the Loader, starts the actual file downloading.
156200
* During the load the methods onLoad, onError and onProgress are called, based on the XHR events.
157201
* You shouldn't normally call this method directly, it's meant to be invoked by the Loader.
158202
*
159-
* @method Phaser.Loader.FileTypes.HTML5AudioFile#load
160-
* @since 3.0.0
203+
* @method Phaser.Loader.FileTypes.VideoFile#load
204+
* @since 3.20.0
161205
*/
162206
load: function ()
163207
{
164208
var loadEvent = this.config.loadEvent;
165-
var asBlob = this.config.asBlob;
166-
var noAudio = this.config.noAudio;
167209

168-
if (asBlob)
210+
if (this.config.asBlob)
169211
{
170-
// console.log('Passing load over to File.load');
171-
172212
File.prototype.load.call(this);
173213
}
174214
else
175215
{
176-
console.log('Loading as Video tag');
177-
178216
this.percentComplete = 0;
179217

180-
var video = document.createElement('video');
181-
182-
video.controls = false;
183-
video.crossOrigin = this.loader.crossOrigin;
184-
185-
if (noAudio)
186-
{
187-
video.muted = true;
188-
video.defaultMuted = true;
189-
190-
video.setAttribute('autoplay', 'autoplay');
191-
}
218+
var video = this.createVideoElement();
192219

193-
video.setAttribute('playsinline', 'playsinline');
194-
video.setAttribute('preload', 'auto');
195-
196-
var _this = this;
197-
198-
this.onVideoLoadHandler = function (event)
199-
{
200-
console.log('onVideoLoadHandler');
201-
console.log(event);
202-
203-
var video = event.target;
204-
205-
video.removeEventListener(_this.config.loadEvent, _this.onVideoLoadHandler, true);
206-
207-
_this.data = video;
208-
209-
_this.resetXHR();
210-
211-
_this.loader.nextFile(_this, true);
212-
};
213-
214-
video.addEventListener(loadEvent, this.onVideoLoadHandler, true);
215-
216-
video.addEventListener('error', function (e)
217-
{
218-
console.log('Load Error');
219-
console.log(e);
220-
}, true);
221-
222-
video.addEventListener('loadstart', function (e)
223-
{
224-
console.log('Load Start');
225-
}, true);
226-
227-
video.addEventListener('loadedmetadata', function (e)
228-
{
229-
console.log('Loaded Meta Data');
230-
}, true);
231-
232-
video.addEventListener('emptied', function (e)
233-
{
234-
console.log('Load Emptied');
235-
}, true);
220+
video.addEventListener(loadEvent, this.onLoadCallback, true);
221+
video.addEventListener('error', this.onErrorCallback, true);
236222

237223
video.src = GetURL(this, this.loader.baseURL);
238224

@@ -258,8 +244,6 @@ VideoFile.create = function (loader, key, urls, loadEvent, asBlob, noAudio, xhrS
258244

259245
var urlConfig = VideoFile.getVideoURL(game, urls);
260246

261-
// console.log(urlConfig);
262-
263247
if (urlConfig)
264248
{
265249
return new VideoFile(loader, key, urlConfig, loadEvent, asBlob, noAudio, xhrSettings);
@@ -299,14 +283,14 @@ VideoFile.getVideoURL = function (game, urls)
299283
};
300284

301285
/**
302-
* Adds an Audio or HTML5Audio file, or array of audio files, to the current load queue.
286+
* Adds a Video file, or array of video files, to the current load queue.
303287
*
304288
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
305289
*
306290
* ```javascript
307291
* function preload ()
308292
* {
309-
* this.load.audio('title', [ 'music/Title.ogg', 'music/Title.mp3', 'music/Title.m4a' ]);
293+
* this.load.video('intro', [ 'video/level1.mp4', 'video/level1.webm', 'video/level1.mov' ]);
310294
* }
311295
* ```
312296
*
@@ -318,40 +302,45 @@ VideoFile.getVideoURL = function (game, urls)
318302
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
319303
* loaded.
320304
*
321-
* The key must be a unique String. It is used to add the file to the global Audio Cache upon a successful load.
322-
* The key should be unique both in terms of files being loaded and files already present in the Audio Cache.
305+
* The key must be a unique String. It is used to add the file to the global Video Cache upon a successful load.
306+
* The key should be unique both in terms of files being loaded and files already present in the Video Cache.
323307
* Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file
324-
* then remove it from the Audio Cache first, before loading a new one.
325-
*
308+
* then remove it from the Video Cache first, before loading a new one.
309+
*
326310
* Instead of passing arguments you can pass a configuration object, such as:
327311
*
328312
* ```javascript
329-
* this.load.audio({
330-
* key: 'title',
331-
* url: [ 'music/Title.ogg', 'music/Title.mp3', 'music/Title.m4a' ]
313+
* this.load.video({
314+
* key: 'intro',
315+
* url: [ 'video/level1.mp4', 'video/level1.webm', 'video/level1.mov' ],
316+
* asBlob: false,
317+
* noAudio: true
332318
* });
333319
* ```
334320
*
335321
* See the documentation for `Phaser.Types.Loader.FileTypes.VideoFileConfig` for more details.
336322
*
337323
* The URLs can be relative or absolute. If the URLs are relative the `Loader.baseURL` and `Loader.path` values will be prepended to them.
338324
*
339-
* Due to different browsers supporting different audio file types you should usually provide your audio files in a variety of formats.
340-
* ogg, mp3 and m4a are the most common. If you provide an array of URLs then the Loader will determine which _one_ file to load based on
341-
* browser support.
342-
*
343-
* If audio has been disabled in your game, either via the game config, or lack of support from the device, then no audio will be loaded.
325+
* Due to different browsers supporting different video file types you should usually provide your video files in a variety of formats.
326+
* mp4, mov and webm are the most common. If you provide an array of URLs then the Loader will determine which _one_ file to load based on
327+
* browser support, starting with the first in the array and progressing to the end.
328+
*
329+
* Unlike most asset-types, videos do not _need_ to be preloaded. You can create a Video Game Object and then call its `loadURL` method,
330+
* to load a video at run-time, rather than in advance.
344331
*
345-
* Note: The ability to load this type of file will only be available if the Audio File type has been built into Phaser.
332+
* Note: The ability to load this type of file will only be available if the Video File type has been built into Phaser.
346333
* It is available in the default build but can be excluded from custom builds.
347334
*
348335
* @method Phaser.Loader.LoaderPlugin#video
349336
* @fires Phaser.Loader.LoaderPlugin#addFileEvent
350337
* @since 3.20.0
351338
*
352339
* @param {(string|Phaser.Types.Loader.FileTypes.VideoFileConfig|Phaser.Types.Loader.FileTypes.VideoFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
353-
* @param {(string|string[])} [urls] - The absolute or relative URL to load the audio files from.
354-
* @param {any} [config] - An object containing an `instances` property for HTML5Audio. Defaults to 1.
340+
* @param {(string|string[])} [urls] - The absolute or relative URL to load the video files from.
341+
* @param {string} [loadEvent='loadeddata'] - The load event to listen for when _not_ loading as a blob. Either `loadeddata`, `canplay` or `canplaythrough`.
342+
* @param {boolean} [asBlob=false] - Load the video as a data blob, or stream it via the Video element?
343+
* @param {boolean} [noAudio=false] - Does the video have an audio track? If not you can enable auto-playing on it.
355344
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings.
356345
*
357346
* @return {Phaser.Loader.LoaderPlugin} The Loader instance.

0 commit comments

Comments
 (0)