Ignore:
Timestamp:
2021-08-04T15:17:15+12:00 (3 years ago)
Author:
davidb
Message:

Implement support for new proxy error responses
Revert to sending audio in batches, with improved fetch usage

Location:
main/trunk/model-interfaces-dev/atea
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/model-interfaces-dev/atea/js/asr/TranscribeService.js

    r35243 r35250  
    33 *
    44 * @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, start_time: Number}[]} metadata The character metadata.
     8 * @property {boolean} success A value indicating if the transcription was successful or not.
    59 * @property {String} transcription The transcription.
    6  * @property {{char: String, start_time: Number}[]} metadata The character metadata.
    7  * @property {String} file_name The name of the file that was transcribed.
    810 */
     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}
    926
    1027/**
     
    2037
    2138    /**
    22      * Uploads files to out transcription API using a fetch request.
     39     * Performs a query to transcribe the given audio files.
    2340     *
    2441     * @param {FileList} files The files to upload.
    25      * @returns {Promise<TranscriptionModel>} A promise for an object representation of the JSON response.
     42     * @returns {Promise<TranscriptionModel[]>} The transcribed aufio file.
    2643     */
    27     async doFetchUpload(files)
     44    async transcribeFiles(files)
    2845    {
    2946        const that = this;
     
    3350        for (let i = 0; i < files.length; i++)
    3451        {
    35             let f = files[i];
    36             let key = "audioFile" + i;
     52            const f = files[i];
     53            const key = "audioFile" + i;
    3754
    3855            formData.append(key, f, f.name);
     
    4158        formData.append("audioFileKeys", audioFileKeys);
    4259
    43         const response = await fetch
    44         (
    45             that.queryUrl,
    46             {
    47                 method: "POST",
    48                 body: formData
    49             }
    50         );
    51 
    52         return response.json();
    53     }
    54 
    55     /**
    56      * @callback TranscriptionPromiseCallback
    57      * @param {Promise<Response>} promise A fetch promise containing an HTTP response.
    58      * @param {String} filename The file that this transcription is for.
    59      * @returns {void}
    60      */
    61 
    62     /**
    63      *
    64      * @param {FileList} files The files to upload
    65      * @param {TranscriptionPromiseCallback} callback A callback made with the fetch promise.
    66      */
    67     doIndividualFetchUpload(files, callback)
    68     {
    69         const that = this;
    70        
    71         for (let f of files)
     60        let response;
     61        try
    7262        {
    73             const formData = new FormData();
    74             formData.append("audioFile", f, f.name);
    75             formData.append("audioFileKeys", "audioFile");
    76 
    77             let promise = fetch
     63            response = await fetch
    7864            (
    7965                that.queryUrl,
     
    8268                    body: formData
    8369                }
    84             )
    85             callback(promise, f.name);
     70            );
    8671        }
     72        catch (e)
     73        {
     74            console.error(`Transcription failed with reason ${e}`);
     75            throw new TranscribeError(undefined, undefined);
     76        }
     77
     78        if (!response.ok)
     79        {
     80            console.error(`Transcription API failed with status ${response.status} and message ${response.statusText}`);
     81            throw new TranscribeError(response.status, response.statusText);
     82        }
     83       
     84        return await response.json();
    8785    }
    8886
     
    132130    // }
    133131}
    134 
    135 
  • main/trunk/model-interfaces-dev/atea/js/asr/asr-controller.js

    r35243 r35250  
    11// The controller for asr.xsl
     2// @ts-nocheck
    23
    34/**
     
    2425/**
    2526 * Loads a remote script.
    26  * https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file
     27 * Found at https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file
    2728 *
    2829 * @param {string} url The URL from which to load the script.
     
    3132function loadScript(url, callback = () => {})
    3233{
    33     // Adding the script tag to the head as suggested before
    34     var head = document.head;
     34    // Append the script to the body element
     35    var body = document.body;
    3536    var script = document.createElement('script');
    3637    script.type = 'text/javascript';
    3738    script.src = url;
    38 
    39     // Then bind the event to the callback function.
    40     // There are several events for cross browser compatibility.
    41     // script.onreadystatechange = callback; // TODO: Does this callback no longer exist?
     39   
    4240    script.onload = callback;
    4341
    44     head.appendChild(script);
     42    body.appendChild(script);
    4543}
    4644
    4745loadScript("./interfaces/atea/js/asr/TranscribeService.js");
    4846
    49 function doAudioUpload()
     47async function doAudioUpload()
    5048{
    5149    const files = $(FILE_UPLOAD_INPUT_NAME)[0].files;
    5250    const transcribeService = new TranscribeService();
    53 
     51   
    5452    $(FILE_UPLOAD_PROGRESS_CONTAINER_NAME).removeClass("asr-hidden");
    5553
    5654    // Remove old transcriptions
    57     const parent = document.querySelector("#transcriptionsList");
    58     while (parent.lastChild) {
    59         parent.removeChild(parent.lastChild);
     55    const transcriptionsList = document.querySelector("#transcriptionsList");
     56    if (transcriptionsList == null)
     57    {
     58        console.error("Cannot find transcriptions list");
     59        return;
    6060    }
    6161
    62     transcribeService.doIndividualFetchUpload(files, (promise, fileName) => {
    63         promise
    64         .then
    65         (
    66             async response =>
    67             {
    68                 /** @type {TranscriptionModel[]} */
    69                 const transcription = await response.json();
     62    while (transcriptionsList.lastChild) {
     63        transcriptionsList.removeChild(transcriptionsList.lastChild);
     64    }
    7065
    71                 // Note that there will only be one transcription here, however the proxy API always returns a list.
    72                 for (let t of transcription) {
    73                     console.log("Inserting one transcription");
    74                     insertTranscription(t);
    75                 }
     66    try
     67    {
     68        const transcriptions = await transcribeService.transcribeFiles(files);
     69        for (const t of transcriptions)
     70        {
     71            if (!t.success) {
     72                insertError(t.file_name, t.log);
    7673            }
    77         )
    78         .catch
    79         (
    80             reason =>
    81             {
    82                 insertError(fileName);
    83                 console.log(`Transcription for file ${fileName} failed with reason ${reason}`);
     74            else {
     75                insertTranscription(t);
    8476            }
    85         );
    86     })
     77        }
     78    }
     79    catch (e)
     80    {
     81        insertError("all", e.statusMessage);
     82    }
    8783
    88     // transcribeService.doFetchUpload(files)
    89     //     .then
    90     //     (
    91     //         transcriptions => {
    92     //             // Insert each new transcription
    93     //             for (let t of transcriptions) {
    94     //                 insertTranscription(t);
    95     //             }
    96     //         },
    97     //         reason => {
    98     //             console.log(reason)
    99     //         }
    100     //     )
    101     //     .catch(error => console.log("Failed to upload audio files for transcription: " + error)) // TODO: display error to user
    102     //     .finally(() => $(FILE_UPLOAD_PROGRESS_CONTAINER_NAME).addClass("asr-hidden"));
    103     return false;
     84    $(FILE_UPLOAD_PROGRESS_CONTAINER_NAME).addClass("asr-hidden");
    10485}
    10586
     
    10788const transcriptionTemplate = document.querySelector('#transcriptionTemplate');
    10889const metadataTemplate = document.querySelector("#metadataTemplate");
    109 const errorTemplate = document.querySelector("#errorTemplate");
    11090
    11191/**
     
    11999    let list = document.querySelector("#transcriptionsList");
    120100
    121     if (list == null || transcriptionTemplate == null) {
    122         console.error("Could not find transcription list and/or template.");
    123         return;
    124     }
    125 
    126101    // Insert a new transcription row
    127102    let clone = transcriptionTemplate.content.firstElementChild.cloneNode(true);
     
    133108    let metadataList = clone.querySelector("#metadataList");
    134109
    135     if (metadataList == null || metadataTemplate == null) {
     110    if (metadataList == null || metadataTemplate == null)
     111    {
    136112        console.error("Could not find metadata list and/or template.");
    137113        return;
     
    139115
    140116    // Insert metadata rows
    141     for (let metadata of transcription.metadata) {
     117    for (let metadata of transcription.metadata)
     118    {
    142119        let metadataClone = metadataTemplate.content.firstElementChild.cloneNode(true);
    143120        let metadataSpans = metadataClone.querySelectorAll("td");
     
    152129}
    153130
     131const errorTemplate = document.querySelector("#errorTemplate");
     132
    154133/**
    155134 * Inserts a transcription error into the DOM.
    156135 *
    157136 * @param {String} fileName
     137 * @param {String | undefined} statusMessage
    158138 */
    159 function insertError(fileName)
     139function insertError(fileName, statusMessage)
    160140{
    161141    // Get the transcription list and template
    162142    let list = document.querySelector("#transcriptionsList");
    163143
    164     if (list == null || errorTemplate == null) {
     144    if (list == null || errorTemplate == null)
     145    {
    165146        console.error("Could not find transcription list and/or error template");
    166147        return;
     
    170151    let clone = errorTemplate.content.firstElementChild.cloneNode(true);
    171152    let spans = clone.querySelectorAll("span");
    172     spans[0].textContent = fileName;
     153    spans[0].textContent = statusMessage;
     154    spans[1].textContent = fileName;
    173155
    174156    list.appendChild(clone);
     
    179161function toggleUploadButtonState(e)
    180162{
    181     if (e.target.files.length <= 0)
     163    if (e.target.files.length <= 0) {
    182164        $(FILE_UPLOAD_BUTTON_NAME).prop("disabled", true);
    183     else
     165    }
     166    else {
    184167        $(FILE_UPLOAD_BUTTON_NAME).prop("disabled", false);
     168    }
    185169}
  • main/trunk/model-interfaces-dev/atea/style/asr.css

    r35243 r35250  
    7373  margin: -.5em -.5em 0;
    7474  padding: .5em;
     75  cursor: pointer;
    7576}
    7677
  • main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl

    r35243 r35250  
    4141       
    4242        <div>
    43             <form onSubmit="return doAudioUpload()" enctype="multipart/form-data">
     43            <form onSubmit="doAudioUpload(); return false;" enctype="multipart/form-data">
    4444                <label for="fileUpload">Audio File:</label>
    4545                <input id="fileUpload" type="file" accept="audio/wav" multiple="multiple" />
     
    6666                        </div>
    6767                        <details>
    68                             <summary>Metadata</summary>
     68                            <summary>Character Information</summary>
    6969                            <table id="metadataList" class="metadata-list">
    7070                                <thead>
     
    8484                <li class="error-list-item">
    8585                    <div>
    86                         Transcription failed!<br />
     86                        Transcription failed: <span></span><br />
    8787                        <b>File: </b><span></span>
    8888                    </div>
Note: See TracChangeset for help on using the changeset viewer.