source: main/trunk/model-interfaces-dev/atea/js/asr/TranscribeService.js@ 35253

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

Disable upload button while transcription is in progress

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