// How to use this script: // (1) Create a new AR Studio project // (2) Add a plane, assign it a material // (3) Attach an ExternalTexture to the newly created material // (4) Add an audio source // (5) Add ExternalVideo capability and whitelist the video domain // (6) Add a script, paste this code // (7) Create a new video: var video = new Video('url', texture, audio); // (8) Call video.play() / video.stop() somewhere in the script var S = require('Scene'); var D = require('Diagnostics'); var T = require('Textures'); var Time = require('Time'); /** * A Video entity that enables you to play a video with some sounds. * * @param {!string} videoUrl - url of video (require TLS) * @param {!ExternalTexture} videoTexture - the external texture object from the scene * @param {AudioSource=} audioSource - the audio source object from the scene * @param {boolean=} autoPlay - whether to play the video right after it's created */ function Video(videoUrl, videoTexture, audioSource, autoPlay) { this.id = Video.id++; this.videoTexture = videoTexture; this.videoUrl = videoUrl; this.audioSource = audioSource; this.deferAudioPlaying = false; this.audioTimer = null; this.playing = false; this.mode = Video.mode.PLAY_AUDIO_RIGHT_AFTER_AVAIL_EVENT; this.delayAudioMs = 1000; // ^ Change those parameters to experiment: // Use PLAY_AUDIO_AFTER_CUSTOM_DELAY to call setTimeout with "delayAudioMs" var that = this; this.videoTexture.state.monitor().subscribe(function (event) { D.log('Video' + that.id + ': received texture event "' + event.newValue + '"'); if (event.newValue === T.ExternalTexture.State.AVAILABLE) { if (that.deferAudioPlaying) { that.deferAudioPlaying = false; // At this point there are 3 things I noted: // (1) the video will actually play after a delay (about 1s) // (2) *sometimes*, the audio will play after a long delay after we do audioSource.play() (about 10s) // (3) if the audio is delayed once, then it won't be delayed the next time you play it! if (that.mode === Video.mode.PLAY_AUDIO_RIGHT_AFTER_AVAIL_EVENT) { D.log('Video' + that.id + ': now play the sound'); that.audioSource.play(); } else if (that.mode === Video.mode.PLAY_AUDIO_AFTER_CUSTOM_DELAY) { var startDate = Date.now(); that.audioTimer = Time.setTimeout(function () { that.audioSource.play(); var delay = Date.now() - startDate; D.log('Video' + that.id + ': audio.play() was called after a ' + delay + 'ms delay'); }, that.delayAudioMs); } } } else if (event.newValue === T.ExternalTexture.State.PENDING) { // Pause sound (in theory) } }); if (autoPlay) this.play(); } Video.id = 0; Video.mode = { PLAY_AUDIO_RIGHT_AFTER_AVAIL_EVENT: 1, PLAY_AUDIO_AFTER_CUSTOM_DELAY: 2 }; /** Play the video object with audio */ Video.prototype.play = function () { if (this.playing) return; this.videoTexture.url = this.videoUrl; if (this.audioSource) this.deferAudioPlaying = true; this.playing = true; }; /** Stop the video and the audio. */ Video.prototype.stop = function () { if (!this.playing) return; this.videoTexture.url = ''; if (this.audioSource) this.audioSource.stopAll(); if (this.audioTimer) { Time.clearInterval(this.audioTimer); this.audioTimer = null; } this.deferAudioPlaying = false; this.playing = false; }; Video.prototype.pause = function () { D.log('There is no way to pause a video right now.'); };