source: main/trunk/model-interfaces-dev/atea/macron-restoration/src/js/MacronRestorationModule.js@ 35716

Last change on this file since 35716 was 35716, checked in by cstephen, 2 years ago

Amend previous commit

File size: 5.9 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
7import { log } from "./Util"
8
9export class MacronRestorationError extends Error {
10 /**
11 * Initialises a new instance of the {@link MacronRestorationError} object.
12 *
13 * @param {Number | undefined} statusCode The HTTP status code of the error.
14 * @param {String | undefined} message The status message.
15 * @param {String | null} fileName The file on which the transcription failed.
16 */
17 constructor(message = undefined, fileName = null, statusCode = -1) {
18 super(message);
19
20 /** @type {String | null} The name of the file that the transcription error occured on. */
21 this.fileName = fileName;
22
23 /** @type {Number | undefined} The status code returned by the API when the erro was generated. */
24 this.statusCode = statusCode;
25 }
26}
27
28/**
29 * A service that performs requests to the macron restoration API.
30 */
31export default class MacronRestorationService {
32 constructor() {
33 /** @type {String} The URL to which query POST requests should be made. */
34 if (process.env.NODE_ENV !== "production") {
35 this.queryUrl = "//localhost:8383/macron-restoration/jsp/servlet/DirectInput";
36 }
37 else {
38 this.queryUrl = "/macron-restoration/jsp/servlet/DirectInput";
39 }
40 }
41
42 /**
43 * Performs a request to the macron restoration API to restore the given input text.
44 * @param {String} input The input text to macronise
45 * @returns The JSON response from the macron restoration API.
46 */
47 async directMacronisation(input) {
48 const that = this;
49
50 try {
51 const response = await fetch(
52 that.queryUrl,
53 {
54 method: "POST",
55 headers: {
56 "Content-Type": "application/x-www-form-urlencoded"
57 },
58 body: `o=json&fragment=${input}`
59 }
60 );
61
62 if (!response.ok) {
63 log(`Macron Restoration API failed with status ${response.status} and message ${response.statusText}`, "error")
64 throw new MacronRestorationError(response.statusText, undefined, response.status);
65 }
66
67 return await response.json();
68 }
69 catch (e) {
70 log(`Macron restoration failed with reason ${e}`, "error");
71 throw new MacronRestorationError(undefined, "Unknown");
72 }
73 }
74
75 /**
76 * Performs chunked queries to transcribe the given audio files, returning the data in iterations.
77 * Data is chunked according to which ever occurs first:
78 * A maximum of three files per request, or;
79 * A maximum of 5 MiB before chunking.
80 *
81 * @param {FileList | File[]} files The files to upload
82 * @returns {AsyncGenerator<TranscriptionModel[]>} The transcribed audio files.
83 * @throws {TranscriptionError} When the transcription request fails to complete.
84 */
85 async* batchFileMacronisation(files) {
86 let filesToSubmit = [];
87 let fileCounter = 0;
88 let byteCounter = 0;
89
90 for (const file of files) {
91 if (fileCounter === this.MAX_BATCH_COUNT || byteCounter > this.BATCH_BYTE_LIMIT) { // 5 MiB
92 yield await this.fileMacronisation(filesToSubmit);
93 filesToSubmit = [];
94 byteCounter = 0;
95 fileCounter = 0;
96 }
97
98 filesToSubmit[fileCounter++] = file;
99 byteCounter += file.size;
100 }
101
102 if (filesToSubmit.length > 0) {
103 yield await this.fileMacronisation(filesToSubmit);
104 }
105 }
106
107 /**
108 * Performs a query to transcribe the given audio files.
109 *
110 * @param {File[]} files The files to upload.
111 * @returns {Promise<TranscriptionModel[]>} The transcribed audio file.
112 * @throws {TranscriptionError} When the transcription request fails to complete.
113 */
114 async fileMacronisation(files) {
115 if (process.env.NODE_ENV !== "production" || files.some(file => file.name === "akl_mi_pk_0002_offline.wav")) {
116 return await this.fileMacronisationTest(files);
117 }
118 else {
119 return await this.fileMacronisationActual(files);
120 }
121 }
122
123 async fileMacronisationTest(files) {
124 const objects = [];
125
126 for (const file of files) {
127 const object = JSON.parse(this.TEST_JSON);
128 object.file_name = file.name;
129 objects.push(object);
130 }
131
132 return objects;
133 }
134
135 /**
136 * Performs a query to transcribe the given audio files.
137 *
138 * @param {FileList | File[]} files The files to upload.
139 * @returns {Promise<TranscriptionModel[]>} The transcribed audio file.
140 * @throws {TranscriptionError} When the transcription request fails to complete.
141 */
142 async fileMacronisationActual(files) {
143 const that = this;
144 const formData = new FormData();
145
146 let audioFileKeys = "";
147 for (let i = 0; i < files.length; i++) {
148 const f = files[i];
149 const key = "audioFile" + i;
150
151 formData.append(key, f, f.name);
152 audioFileKeys += key + "|";
153 }
154 formData.append("audioFileKeys", audioFileKeys);
155
156 try {
157 const response = await fetch(
158 that.queryUrl,
159 {
160 method: "POST",
161 body: formData
162 }
163 );
164
165 if (!response.ok) {
166 log(`Transcription API failed with status ${response.status} and message ${response.statusText}`, "error")
167 throw new MacronRestorationError(response.statusText, undefined, response.status);
168 }
169
170 return await response.json();
171 }
172 catch (e) {
173 log(`Transcription failed with reason ${e}`, "error");
174 throw new MacronRestorationError(undefined, "Unknown");
175 }
176 }
177}
Note: See TracBrowser for help on using the repository browser.