source: main/trunk/model-interfaces-dev/atea/korero-maori-asr/src/App.vue@ 35426

Last change on this file since 35426 was 35426, checked in by cstephen, 3 years ago

Improve audio time bar implementation

File size: 4.3 KB
Line 
1<template>
2 <!-- Used to calculate the character size of our monospace font -->
3 <span class="monospace-font-sizer">ngā tama a rangi</span>
4
5 <div class="paper">
6 <AudioUpload />
7 </div>
8
9 <ul id="transcription-list" class="list-view">
10 <transition-group name="transcription-list">
11 <li class="list-item transcription-list-item" v-for="[id, transcription] in transcriptions" :key="id">
12 <TranscriptionItem :transcription="transcription" />
13 </li>
14 </transition-group>
15 </ul>
16</template>
17
18<style lang="scss">
19#transcription-list {
20 margin-bottom: 1em;
21}
22
23.monospace-font-sizer {
24 font: var(--monospace-font);
25 padding: 0;
26 position: absolute;
27 top: -100px;
28}
29
30.transform-rotate180 {
31 --transition-duration: 0.4s;
32 transition-duration: var(--transition-duration);
33
34 transform: rotate(180deg);
35}
36
37.transform-slideout-up {
38 --transition-duration: 0.4s;
39 transition-duration: var(--transition-duration);
40
41 z-index: -1;
42 transform: translate(0, -100%);
43 opacity: 0;
44}
45
46.transcription-list-item {
47 transition: all 0.8s ease;
48}
49
50.transcription-list-leave-to {
51 opacity: 0;
52 transform: translateX(30%);
53}
54
55.transcription-list-leave-active {
56 position: absolute;
57}
58</style>
59
60<script>
61import { mapState } from "vuex";
62import AudioUpload from "./components/AudioUpload.vue"
63import TranscriptionItem from "./components/TranscriptionItem.vue"
64
65export default {
66 name: "App",
67 components: {
68 AudioUpload,
69 TranscriptionItem
70 },
71 data() {
72 return {
73 /** @type {{id: String, url: String} | null} */
74 currentlyLoadedAudio: null,
75 player: new Audio()
76 }
77 },
78 computed: mapState({
79 translations: state => state.translations,
80 transcriptions: state => state.rawTranscriptions,
81 playbackState: state => state.playbackState,
82 shouldPlayAudio: state => state.playbackState.isPlaying
83 }),
84 watch: {
85 async playbackState(newValue) {
86 if (!newValue.isPlaying) {
87 return;
88 }
89
90 const transcription = this.transcriptions.get(newValue.id);
91 loadTranscriptionAudio(this.player, transcription, this.currentlyLoadedAudio);
92
93 let playbackTime = 0;
94 if (newValue.currentTime > 0) {
95 playbackTime = newValue.currentTime;
96 }
97
98 this.player.currentTime = playbackTime;
99 await this.player.play();
100 }//,
101 // shouldPlayAudio(newValue) {
102 // if (newValue && this.$refs.audioPlayer.paused) {
103 // this.$refs.audioPlayer.play();
104 // }
105 // else if (!newValue && !this.$refs.audioPlayer.paused) {
106 // this.$refs.audioPlayer.pause();
107 // }
108 // }
109 },
110 mounted() {
111 pollAudioTime(this.player, this.$store);
112 }
113}
114
115// Adapted from https://davidwalsh.name/javascript-polling
116function pollAudioTime(audioElement, store) {
117 var lastTime = 0;
118 (function p() {
119 if (audioElement.currentTime !== lastTime) {
120 lastTime = audioElement.currentTime;
121 store.commit("setCurrentPlaybackTime", lastTime);
122 store.commit("setCurrentlyPlaying", true);
123 }
124 else {
125 store.commit("setCurrentlyPlaying", false);
126 }
127
128 setTimeout(p, 33); // Slightly more than 30hz
129 })();
130}
131
132/**
133 * Loads an audio file.
134 * @param {Audio} player The audio player.
135 * @param {TranscriptionViewModel} transcription The name of the requested audio file.
136 * @param {{id: String, url: String} | null} current The currently loaded audio.
137 * @returns {{id: String, url: String}} If a new audio file was loaded, a new audio tracking object, else the current one.
138 */
139function loadTranscriptionAudio(player, transcription, current) {
140 if (current == null || current.id !== transcription.id) {
141 // TODO: Need to profile on some larger tracks; this may not be worth it? Better to cache a URL object instead?
142 if (current !== null) {
143 URL.revokeObjectURL(current.url);
144 }
145
146 const urlObject = URL.createObjectURL(transcription.file);
147 player.src = urlObject;
148 player.load();
149
150 return { id: transcription.id, url: urlObject };
151 }
152
153 return current;
154}
155</script>
Note: See TracBrowser for help on using the repository browser.