Changeset 35255


Ignore:
Timestamp:
2021-08-05T16:55:26+12:00 (3 years ago)
Author:
davidb
Message:

Add audio playback from specific characters

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

Legend:

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

    r35253 r35255  
    33
    44/**
    5  * The name of the file input that audio files can be uploaded to.
    6  */
     5* The name of the file input that audio files can be uploaded to.
     6*/
    77const FILE_UPLOAD_INPUT_NAME = "#fileUpload";
    88
    99/**
    10  * The name of the container that holds the progress display for the audio upload.
    11  */
     10* The name of the container that holds the progress display for the audio upload.
     11*/
    1212const FILE_UPLOAD_PROGRESS_CONTAINER_NAME = "#prgFileUploadContainer";
    1313
    1414/**
    15  * The name of the button that triggers the audio upload
    16  */
    17 const FILE_UPLOAD_BUTTON_NAME = "#btnFileUpload";
    18 
    19 /**
    20  * @callback loadScriptCallback
    21  * @param {Event} ev The event
    22  * @returns {void}
    23  */
    24 
    25 /**
    26  * Loads a remote script.
    27  * Found at https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file
    28  *
    29  * @param {string} url The URL from which to load the script.
    30  * @param {loadScriptCallback} callback Callback performed when the script has been loaded.
    31  */
     15* @callback loadScriptCallback
     16* @param {Event} ev The event
     17* @returns {void}
     18*/
     19
     20/**
     21* Loads a remote script.
     22* Found at https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file
     23*
     24* @param {string} url The URL from which to load the script.
     25* @param {loadScriptCallback} callback Callback performed when the script has been loaded.
     26*/
    3227function loadScript(url, callback = () => {})
    3328{
     
    3934   
    4035    script.onload = callback;
    41 
     36   
    4237    body.appendChild(script);
    4338}
    4439
    4540loadScript("./interfaces/atea/js/asr/TranscribeService.js");
     41
     42/** @type {HTMLAudioElement} */
     43const transcriptionAudioElement = document.getElementById("transcriptionAudio");
     44
     45/** @type {HTMLSourceElement} */
     46const transcriptionAudioSourceElement = document.getElementById("transcriptionAudioSource");
    4647
    4748async function doAudioUpload()
     
    4950    const files = $(FILE_UPLOAD_INPUT_NAME)[0].files;
    5051    const transcribeService = new TranscribeService();
    51 
     52   
     53    transcriptionAudioSourceElement.src = URL.createObjectURL(files[0]);
     54    transcriptionAudioElement.load();
     55   
    5256    $(FILE_UPLOAD_INPUT_NAME).prop("disabled", true);
    5357    $(FILE_UPLOAD_PROGRESS_CONTAINER_NAME).removeClass("asr-hidden");
    54 
     58   
    5559    // Remove old transcriptions
    56     const transcriptionsList = document.querySelector("#transcriptionsList");
     60    const transcriptionsList = document.getElementById("transcriptionsList");
    5761    if (transcriptionsList == null)
    5862    {
     
    6064        return;
    6165    }
    62 
     66   
    6367    while (transcriptionsList.lastChild) {
    6468        transcriptionsList.removeChild(transcriptionsList.lastChild);
    6569    }
    66 
     70   
    6771    try
    6872    {
     
    8589        insertError("all", e.statusMessage);
    8690    }
    87 
     91   
    8892    $(FILE_UPLOAD_PROGRESS_CONTAINER_NAME).addClass("asr-hidden");
    8993    $(FILE_UPLOAD_INPUT_NAME).prop("disabled", false);
    9094}
    9195
    92 // Adapted from https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
    93 const transcriptionTemplate = document.querySelector('#transcriptionTemplate');
    94 const metadataTemplate = document.querySelector("#metadataTemplate");
    95 
    96 /**
    97  * Inserts a transcription object into the DOM.
    98  *
    99  * @param {TranscriptionModel} transcription The transcription to insert.
    100  */
     96/** @type {HTMLTemplateElement} */
     97const transcriptionTemplate = document.getElementById("transcriptionTemplate");
     98
     99/** @type {HTMLTemplateElement} */
     100const metadataTemplate = document.getElementById("metadataTemplate");
     101
     102/**
     103* Inserts a transcription object into the DOM.
     104* Adapted from https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
     105*
     106* @param {TranscriptionModel} transcription The transcription to insert.
     107*/
    101108function insertTranscription(transcription)
    102109{
    103110    // Get the transcription list and template
    104     let list = document.querySelector("#transcriptionsList");
    105 
     111    let list = document.getElementById("transcriptionsList");
     112   
    106113    // Insert a new transcription row
    107114    let clone = transcriptionTemplate.content.firstElementChild.cloneNode(true);
     
    109116    spans[0].textContent = transcription.file_name;
    110117    spans[1].textContent = transcription.transcription;
    111 
     118   
    112119    // Get the metadata list and template
    113120    let metadataList = clone.querySelector("#metadataList");
    114 
     121   
    115122    if (metadataList == null || metadataTemplate == null)
    116123    {
     
    118125        return;
    119126    }
    120 
     127   
    121128    // Insert metadata rows
    122129    for (let metadata of transcription.metadata)
    123130    {
    124         let metadataClone = metadataTemplate.content.firstElementChild.cloneNode(true);
    125         let metadataSpans = metadataClone.querySelectorAll("td");
    126    
    127         metadataSpans[0].textContent = metadata.char;
    128         metadataSpans[1].textContent = metadata.start_time;
    129 
     131        const metadataClone = metadataTemplate.content.firstElementChild.cloneNode(true);
     132        const p = metadataClone.querySelector("p");
     133       
     134        /** @type {HTMLButtonElement} */
     135        const button = metadataClone.querySelector("button");
     136       
     137        button.onclick = function()
     138        {
     139            transcriptionAudioElement.currentTime = metadata.start_time;
     140            transcriptionAudioElement.play();
     141        }
     142       
     143        if (metadata.char == ' ') {
     144            p.textContent = "\u00A0 " // This helps with formatting, as elements that only contain whitespace are collapsed.
     145        }
     146        else {
     147            p.textContent = metadata.char;
     148        }
     149       
    130150        metadataList.appendChild(metadataClone);
    131151    }
    132 
     152   
    133153    list.appendChild(clone);
    134154}
     
    137157
    138158/**
    139  * Inserts a transcription error into the DOM.
    140  *
    141  * @param {String} fileName
    142  * @param {String | undefined} statusMessage
    143  */
     159* Inserts a transcription error into the DOM.
     160*
     161* @param {String} fileName
     162* @param {String | undefined} statusMessage
     163*/
    144164function insertError(fileName, statusMessage)
    145165{
    146166    // Get the transcription list and template
    147167    let list = document.querySelector("#transcriptionsList");
    148 
     168   
    149169    if (list == null || errorTemplate == null)
    150170    {
     
    152172        return;
    153173    }
    154 
     174   
    155175    // Insert a new transcription row
    156176    let clone = errorTemplate.content.firstElementChild.cloneNode(true);
     
    158178    spans[0].textContent = statusMessage;
    159179    spans[1].textContent = fileName;
    160 
     180   
    161181    list.appendChild(clone);
    162182}
     
    167187{
    168188    if (e.target.files.length <= 0) {
    169         $(FILE_UPLOAD_BUTTON_NAME).prop("disabled", true);
     189        $("#btnFileUpload").prop("disabled", true);
    170190    }
    171191    else {
    172         $(FILE_UPLOAD_BUTTON_NAME).prop("disabled", false);
    173     }
    174 }
     192        $("#btnFileUpload").prop("disabled", false);
     193    }
     194}
     195
     196$(function() {
     197    // whenever we hover over a menu item that has a submenu
     198    $('.tooltip-parent').on('mouseover', function() {
     199        var $menuItem = $(this),
     200        $submenuWrapper = $('> .tooltip-wrapper', $menuItem);
     201       
     202        // grab the menu item's position relative to its positioned parent
     203        var menuItemPos = $menuItem.position();
     204       
     205        // place the submenu in the correct position relevant to the menu item
     206        $submenuWrapper.css({
     207            top: menuItemPos.top,
     208            left: menuItemPos.left + Math.round($menuItem.outerWidth() * 0.75)
     209        });
     210    });
     211});
  • main/trunk/model-interfaces-dev/atea/style/asr.css

    r35252 r35255  
    11.asr-hidden {
    2   display: none;
     2    display: none;
    33}
    44
    55.transcription-list {
    6   padding: 0;
     6    padding: 0;
    77}
    88
    99.transcription-list-item {
    10   list-style-type: none;
    11   border: 1px solid black;
    12   border-radius: 5px;
    13   margin-bottom: 5px;
    14   padding: 1em;
     10    list-style-type: none;
     11    border: 1px solid black;
     12    border-radius: 5px;
     13    margin-bottom: 5px;
     14    padding: 1em;
    1515}
    1616
    1717.transcription-list-item:last-child {
    18   margin-bottom: 0;
     18    margin-bottom: 0;
    1919}
    2020
    2121.transcription-list-item .spaced-block, .error-list-item .spaced-block {
    22   margin-bottom: 8px;
     22    margin-bottom: 8px;
    2323}
    2424
    2525.transcription-list-item .spaced-block:last-child, .error-list-item .spaced-block:last-child {
    26   margin-bottom: 0;
     26    margin-bottom: 0;
    2727}
    2828
    2929.error-list-item {
    30   list-style-type: none;
    31   background-color: rgba(255, 0, 0, 0.329);
    32   border: 1px solid rgba(255, 0, 0, 0.651);
    33   border-radius: 5px;
    34   margin-bottom: 5px;
    35   padding: 1em;
     30    list-style-type: none;
     31    background-color: rgba(255, 0, 0, 0.329);
     32    border: 1px solid rgba(255, 0, 0, 0.651);
     33    border-radius: 5px;
     34    margin-bottom: 5px;
     35    padding: 1em;
    3636}
    3737
    38 .metadata-list th {
    39   text-align: left;
    40   width: 6em;
     38.metadata-list {
     39    font-size: 16px;
     40    padding: 0;
     41    list-style-type: none;
     42    overflow-x: auto;
     43    overflow-y: hidden;
     44    display: flex;
    4145}
    4246
    43 .metadata-list th {
    44   border-right: 1px solid black;
    45   border-bottom: 1px solid black;
     47.metadata-list-container {
     48    position: relative;
    4649}
    4750
    48 .metadata-list td {
    49   border-right: 1px solid black;
     51.metadata-list-item {
     52    z-index: 1;
     53    width: 1.5em;
     54    border-right: 1px solid black;
     55    text-align: center;
     56    vertical-align: middle;
    5057}
    5158
    52 .metadata-list th:last-child, td:last-child {
    53   border-right: none;
     59.metadata-list-item .spaced-block {
     60    width: 100%;
    5461}
    5562
    56 .metadata-list tr {
    57   border-bottom: 1px solid black;
     63.metadata-list-item button {
     64    padding: 0;
    5865}
    5966
    60 .metadata-list tr:last-child {
    61   border-bottom: none;
     67.metadata-list-item pre {
     68    margin: 0;
     69    padding: 0;
    6270}
    6371
     72.tooltip-parent {
     73    position: static;
     74}
     75
     76.tooltip-parent:hover .tooltip-wrapper {
     77    display: block;
     78}
     79
     80.tooltip-parent .tooltip-wrapper {
     81    position: absolute;
     82    z-index: 10;
     83    display: none;
     84}
     85
     86.tooltip {
     87    width: 120px;
     88    background-color: black;
     89    color: #fff;
     90    text-align: center;
     91    padding: 5px 0;
     92    border-radius: 6px;
     93}
    6494
    6595details {
    66   border: 1px solid #aaa;
    67   border-radius: 4px;
    68   padding: .5em .5em 0;
     96    border: 1px solid #aaa;
     97    border-radius: 4px;
     98    padding: .5em .5em 0;
    6999}
    70100
    71101summary {
    72   font-weight: bold;
    73   margin: -.5em -.5em 0;
    74   padding: .5em;
    75   cursor: pointer;
     102    font-weight: bold;
     103    margin: -.5em -.5em 0;
     104    padding: .5em;
     105    cursor: pointer;
    76106}
    77107
    78108details[open] {
    79   padding: .5em;
     109    padding: .5em;
    80110}
    81111
    82112details[open] summary {
    83   border-bottom: 1px solid #aaa;
    84   margin-bottom: .5em;
     113    border-bottom: 1px solid #aaa;
     114    margin-bottom: .5em;
    85115}
  • main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl

    r35253 r35255  
    4141       
    4242        <div>
    43             <form onSubmit="doAudioUpload(); return false;" 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" />
     
    5454
    5555        <div id="transcriptionsDisplayContainer">
     56            <audio id="transcriptionAudio">
     57                <source id="transcriptionAudioSource" src="" />
     58            </audio>
     59
    5660            <ul id="transcriptionsList" class="transcription-list"></ul>
    5761
     
    6064                    <div>
    6165                        <div class="spaced-block">
    62                             <b>File: </b><span></span>
     66                            <b>File: </b><span></span>
    6367                        </div>
    6468                        <div class="spaced-block">
     
    6771                        <details>
    6872                            <summary>Character Information</summary>
    69                             <table id="metadataList" class="metadata-list">
    70                                 <thead>
    71                                     <tr>
    72                                         <th>Character</th>
    73                                         <th>Start Time</th>
    74                                     </tr>
    75                                 </thead>
    76                                 <tbody></tbody>
    77                             </table>
     73                            <div class="metadata-list-container">
     74                                <ul id="metadataList" class="metadata-list"></ul>
     75                            </div>
    7876                        </details>
    7977                    </div>
     
    9593
    9694            <template id="metadataTemplate">
    97                 <tr>
    98                     <td></td>
    99                     <td></td>
    100                 </tr>
     95                <!-- <li class="metadata-list-item tooltip-parent tooltip">
     96                    <div class="spaced-block">
     97                        <p></p>
     98                    </div>
     99                    <div class="spaced-block">
     100                        <button type="button"><img src="interfaces/{$interface_name}/assets/play_arrow_black_18dp.svg" /></button>
     101                    </div>
     102                    <div class="tooltip-wrapper">
     103                        <span class="tooltip">0.02</span>
     104                    </div>
     105                </li> -->
     106                <li class="metadata-list-item">
     107                    <div class="spaced-block">
     108                        <p></p>
     109                    </div>
     110                    <div class="spaced-block">
     111                        <button type="button"><img src="interfaces/{$interface_name}/assets/play_arrow_black_18dp.svg" /></button>
     112                    </div>
     113                </li>
    101114            </template>
    102115        </div>
Note: See TracChangeset for help on using the changeset viewer.