source: gs3-installations/atea/trunk/interfaces/atea/korero-maori-asr/src/js/AudioPlaybackModule.js@ 36872

Last change on this file since 36872 was 36872, checked in by cstephen, 18 months ago

Update the korero-maori-asr project to fix dependency vunerabilities

File size: 5.2 KB
RevLine 
[35445]1/**
2 * @file Provides an interface for playing transcription audio.
3 * @author Carl Stephens
4 * @module
5 */
6
7class LoadedAudio {
8 /**
9 * Initialises a new instance of the {@link LoadedAudio} class.
10 * @param {String | null} id The ID of the transcription for which this audio belongs to.
11 * @param {String | null} url The audio object URL.
12 */
13 constructor(id, url) {
14 /** @type {String | null} The ID of the transcription for which this audio belongs to. */
15 this.id = id;
16
17 /** @type {String | null} The audio object URL. */
18 this.url = url;
19 }
20}
21
22/**
23 * Polls an audio element's current time and updates the vuex store accordingly.
24 * @param {Audio} audioElement The audio element.
25 * @param {*} store The vuex store to update.
26 */
27function pollAudioTime(audioElement, store) {
[36872]28 let lastTime = 0;
[35445]29
[35446]30 (function poll() {
[35445]31 if (audioElement.currentTime !== lastTime) {
32 lastTime = audioElement.currentTime;
[35450]33 store.commit("playbackStateSetTime", { id: store.state.playbackState.id, time: lastTime });
[35445]34 }
35
[35502]36 requestAnimationFrame(poll);
[35445]37 })();
38}
39
40/**
41 * Loads an audio file.
[35631]42 * @param {HTMLAudioElement} player The audio player.
[35445]43 * @param {TranscriptionViewModel} transcription The name of the requested audio file.
44 * @param {LoadedAudio} current The currently loaded audio.
45 * @returns {LoadedAudio} If a new audio file was loaded, a new audio tracking object, else the current one.
46 */
47function loadAudio(player, transcription, current) {
48 // TODO: Need to profile on some larger tracks; this may not be worth it? Better to cache a URL object instead?
49 if (current.url !== null) {
50 URL.revokeObjectURL(current.url);
51 }
52
53 const urlObject = URL.createObjectURL(transcription.file);
54 player.src = urlObject;
55 player.load();
56
57 return new LoadedAudio(transcription.id, urlObject);
58}
59
60export default class AudioPlayback {
61 /**
62 * Initialises the {@link AudioPlayback} class.
63 * @param {*} store The vuex store to update.
64 */
65 static initialise(store) {
66 /** @type The vuex store. */
67 this.store = store;
68
69 this.player = new Audio();
70 this.loadedAudio = new LoadedAudio(null, null);
[35631]71 this.requestedPlaybackTime = 0;
[35445]72
[35446]73 pollAudioTime(this.player, store);
74
75 this.player.addEventListener("ended", function() {
76 store.commit("playbackStateSetIsPlaying", false);
77 });
[35445]78 }
79
[35631]80 static onCanPlayThrough() {
81 AudioPlayback.player.removeEventListener("canplaythrough", AudioPlayback.onCanPlayThrough);
82
83 AudioPlayback.player.currentTime = AudioPlayback.requestedPlaybackTime;
84 AudioPlayback.store.commit("playbackStateSetLength", { id: AudioPlayback.loadedAudio.id, time: AudioPlayback.player.duration });
85 }
86
[35445]87 /**
[35631]88 * Loads a transcription's audio file.
89 * @param {String} id The ID of the transcription to load the audio of.
90 * @param {Number} startTime The time into the audio to set the current playback time to. Leave negative to select the last value, or zero.
[35445]91 */
[35631]92 static async load(id, startTime = -1) {
93 this.player.addEventListener("canplaythrough", this.onCanPlayThrough);
94
[35450]95 const playbackTimes = this.store.state.playbackState.playbackTimes;
[35445]96
[35631]97 this.requestedPlaybackTime = startTime;
[35450]98 if (playbackTimes.has(id) && startTime < 0) {
[35631]99 this.requestedPlaybackTime = playbackTimes.get(id);
[35445]100 }
101
[35446]102 if (this.loadedAudio.id !== id) {
103 this.loadedAudio = loadAudio(this.player, this.store.state.rawTranscriptions.get(id), this.loadedAudio);
104
105 this.store.commit("playbackStateSetID", id);
106 }
107
[35631]108 this.player.currentTime = AudioPlayback.requestedPlaybackTime;
109 this.store.commit("playbackStateSetLength", { id: id, time: this.player.duration });
110 }
111
112 /**
113 * Plays a transcription's audio file.
114 * @param {String} id The ID of the transcription to play audio for.
115 * @param {Number} startTime The time into the audio at which to start playing. Leave negative to resume playback if paused.
116 */
117 static async play(id, startTime = -1) {
[35755]118 // Start at the beginning if we've reached the end
119 if (this.player.duration <= this.player.currentTime && startTime < 0) {
120 await this.load(id, 0);
121 }
122 else {
123 await this.load(id, startTime);
124 }
125
[35445]126 await this.player.play();
[35446]127 this.store.commit("playbackStateSetIsPlaying", true);
[35445]128 }
129
[35450]130 /**
[35451]131 * Sets the current time of the audio player.
132 * @param {Number} time The time to scrub to.
133 * @param {Boolean} fromCurrent Indicates if the time is an offset.
134 */
135 static scrub(time, fromCurrent) {
136 const newTime = fromCurrent ? this.player.currentTime + time : time;
137 this.player.currentTime = newTime;
138 }
139
140 /**
[35450]141 * Pauses playback.
142 */
[35445]143 static pause() {
144 this.player.pause();
[35446]145 this.store.commit("playbackStateSetIsPlaying", false);
[35445]146 }
[35802]147
148 /**
149 * Resumes playback.
150 * @param {Number} startTime The time into the audio at which to resume playback.
151 */
152 static resume(startTime = -1) {
153 this.play(this.loadedAudio.id, startTime);
154 }
[35445]155}
Note: See TracBrowser for help on using the repository browser.