source: main/trunk/model-interfaces-dev/atea/js/asr/TranscribeModule.js@ 35284

Last change on this file since 35284 was 35284, checked in by davidb, 3 years ago

Convert error templating to Vue

File size: 6.2 KB
Line 
1/**
2 * @file Defines components that are used to interact with the transcription proxy servlet.
3 * @author Carl Stephens
4 * @module
5 */
6
7export class TranscriptionModel
8{
9 /**
10 * The transcription object returned from our transcription endpoint.
11 *
12 * @param {String} file_name The name of the file that was transcribed.
13 * @param {String} log A note of how the transcription was processed.
14 * @param {{char: String, confidence: Number, start_time: Number}[]} metadata The character metadata.
15 * @param {boolean} success A value indicating if the transcription was successful or not.
16 * @param {String} transcription The transcription.
17 */
18 constructor(file_name, log, metadata, success, transcription)
19 {
20 this.file_name = file_name;
21 this.log = log;
22 this.metadata = metadata;
23 this.success = success;
24 this.transcription = transcription;
25 }
26}
27
28export class TranscriptionError extends Error
29{
30 /**
31 * Initialises a new instance of the {@link TranscriptionError} object.
32 *
33 * @param {Number | undefined} statusCode The HTTP status code of the error.
34 * @param {String | undefined} message The status message.
35 * @param {String | null} file The file on which the transcription failed.
36 */
37 constructor(message = undefined, file = null, statusCode = -1)
38 {
39 super(message);
40 //this.message = message;
41
42 this.file = file;
43 this.statusCode = statusCode;
44 }
45}
46
47/**
48 * A service that uploads audio files in a multipart request to the Korero Maori API Interface servlet, and interprets the result.
49 */
50export class TranscribeService
51{
52 constructor()
53 {
54 /** @type {String} The URL to which query POST requests should be made. */
55 this.queryUrl = "/gs3-koreromaori/transcribe/test";
56
57 /** @type {Number} The maximum number of files which can be transcribed in one request to the API. */
58 this.MAX_BATCH_COUNT = 3;
59
60 /** @type {Number} The soft upper limit on how many bytes can be submitted in one request. */
61 this.BATCH_BYTE_LIMIT = 5242880; // 5 MiB
62 }
63
64 /**
65 * Performs chunked queries to transcribe the given audio files, returning the data in iterations.
66 * Data is chunked according to which ever occurs first:
67 * A maximum of three files per request, or;
68 * A maximum of 5 MiB before chunking.
69 *
70 * @param {FileList} files The files to upload
71 * @returns {AsyncGenerator<TranscriptionModel[]>} The transcribed audio files.
72 * @throws {TranscriptionError} When the transcription request fails to complete.
73 */
74 async* batchTranscribeFiles(files)
75 {
76 let filesToSubmit = [];
77 let fileCounter = 0;
78 let byteCounter = 0;
79
80 for (let file of files)
81 {
82 if (fileCounter == this.MAX_BATCH_COUNT || byteCounter > this.BATCH_BYTE_LIMIT) // 5 MiB
83 {
84 yield await this.transcribeFiles(filesToSubmit);
85 filesToSubmit = [];
86 byteCounter = 0;
87 fileCounter = 0;
88 }
89
90 filesToSubmit[fileCounter++] = file;
91 byteCounter += file.size;
92 }
93
94 if (filesToSubmit.length > 0) {
95 yield await this.transcribeFiles(filesToSubmit);
96 }
97 }
98
99 /**
100 * Performs a query to transcribe the given audio files.
101 *
102 * @param {FileList | File[]} files The files to upload.
103 * @returns {Promise<TranscriptionModel[]>} The transcribed audio file.
104 * @throws {TranscriptionError} When the transcription request fails to complete.
105 */
106 async transcribeFiles(files)
107 {
108 const that = this;
109 const formData = new FormData();
110
111 let audioFileKeys = "";
112 for (let i = 0; i < files.length; i++)
113 {
114 const f = files[i];
115 const key = "audioFile" + i;
116
117 formData.append(key, f, f.name);
118 audioFileKeys += key + "|";
119 }
120 formData.append("audioFileKeys", audioFileKeys);
121
122 let response;
123 try
124 {
125 response = await fetch(
126 that.queryUrl,
127 {
128 method: "POST",
129 body: formData
130 }
131 );
132 }
133 catch (e)
134 {
135 console.error(`Transcription failed with reason ${e}`);
136 throw new TranscriptionError(undefined, "Unknown");
137 }
138
139 if (!response.ok)
140 {
141 console.error(`Transcription API failed with status ${response.status} and message ${response.statusText}`);
142 throw new TranscriptionError(response.statusText, undefined, response.status);
143 }
144
145 return await response.json();
146 }
147
148 // OBSOLETE. Kept for reference purposes on XMLHttpRequest usage. See transcribeFiles instead.
149 //
150 // Based on https://stackoverflow.com/questions/2320069/jquery-ajax-file-upload
151 // doUpload(files, resultCallback, progressCallback)
152 // {
153 // let that = this;
154 // let formData = new FormData();
155
156 // let audioFileKeys = "";
157 // for (let f of files)
158 // {
159 // formData.append(f.name, f, f.name);
160 // audioFileKeys += f.name + "|";
161 // }
162 // formData.append("audioFileKeys", audioFileKeys);
163
164 // $.ajax({
165 // type: "POST",
166 // url: this.queryUrl,
167 // xhr: function ()
168 // {
169 // var myXhr = $.ajaxSettings.xhr();
170 // if (myXhr.upload && progressCallback != undefined)
171 // {
172 // myXhr.upload.addEventListener("progress", progressCallback, false);
173 // }
174 // return myXhr;
175 // },
176 // success: function (data)
177 // {
178 // resultCallback(data);
179 // },
180 // error: function (error)
181 // {
182 // console.error("Failed to upload file via AJAX POST: " + error);
183 // },
184 // async: true,
185 // data: formData,
186 // cache: false,
187 // contentType: false,
188 // processData: false,
189 // timeout: 60000 // TODO: Consider if we need a longer timeout.
190 // });
191 // }
192}
Note: See TracBrowser for help on using the repository browser.