Skip to content

Instantly share code, notes, and snippets.

@neeh
Created June 1, 2018 15:37
Show Gist options
  • Select an option

  • Save neeh/9f22f53cc660a56f637a841a58c23f49 to your computer and use it in GitHub Desktop.

Select an option

Save neeh/9f22f53cc660a56f637a841a58c23f49 to your computer and use it in GitHub Desktop.

Revisions

  1. neeh created this gist Jun 1, 2018.
    108 changes: 108 additions & 0 deletions ar-video.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    // 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.');
    };