Changeset 36163


Ignore:
Timestamp:
2022-05-09T14:43:48+12:00 (5 months ago)
Author:
davidb
Message:

Tidy up in TK Labels; Introducing enriched audio playback using wavesurfer and its ability to have audio regions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/web/interfaces/default/js/utility_scripts.js

    r36145 r36163  
    167167}
    168168
     169// TK Label Scripts
     170
    169171var tkMetadataSetStatus = "needs-to-be-loaded";
    170172var tkMetadataElements = null;
     
    192194                        let popupText = document.createElement("span");
    193195                        let heading = "<h1>Traditional Knowledge Label:<br><h2>" + name + "</h2></h1>";
    194                         let moreInformation = "<br> For more information about TK Labels, <a href='https://localcontexts.org/labels/traditional-knowledge-labels/' target='_blank'>click here.</a>";
     196                        let moreInformation = "<br> For more information about TK Labels, ";
     197                        let link = document.createElement("a");
     198                        link.innerHTML = "click here.";
     199                        link.href = "https://localcontexts.org/labels/traditional-knowledge-labels/";
     200                        link.target = "_blank";
    195201                        popupText.innerHTML = heading + comment + moreInformation;
     202                        popupText.appendChild(link);
    196203                        let closeButton = document.createElement("span");
    197204                        closeButton.innerHTML = "&#215;";
     
    253260};
    254261
    255 
     262// Audio Scripts for Enriched Playback
     263
     264function loadAudio(audio, sectionData) {
     265   var speakerObjects = [];
     266   var uniqueSpeakers;
     267   var prevColour;
     268   // const inputFile = "output.csv";
     269   const inputFile = sectionData;
     270   // audio = "audio/akl_mi_pk_0002.wav";
     271   var itemType;
     272
     273   var wavesurfer = WaveSurfer.create({
     274      container: document.querySelector('#waveform'),
     275      backend: 'MediaElement',
     276      backgroundColor: 'rgb(54, 73, 78)',
     277      waveColor: 'white',
     278      progressColor: '#F8C537',
     279      barWidth: 2,
     280      barHeight: 1,
     281      barGap: 2,
     282      barRadius: 1,
     283      cursorColor: 'black',
     284      plugins: [
     285         WaveSurfer.regions.create(),
     286         WaveSurfer.timeline.create({
     287            container: "#wave-timeline",
     288            primaryColor: "white",
     289            secondaryColor: "white",
     290            primaryFontColor: "white",
     291            secondaryFontColor: "white"
     292         }),
     293      ],
     294   });
     295
     296   // wavesurfer.load('https://wavesurfer-js.org/example/elan/transcripts/001z.mp3');
     297   wavesurfer.load(audio);
     298
     299   wavesurfer.on('region-click', function(region, e) {
     300      e.stopPropagation();
     301      regionMouseEvent(region, true);
     302      wavesurfer.play(region.start);
     303      // region.play();
     304   });
     305
     306   wavesurfer.on('region-mouseenter', function(region) { regionMouseEvent(region, true); });
     307   wavesurfer.on('region-mouseleave', function(region) {
     308      if (wavesurfer.getCurrentTime() <= region.end && wavesurfer.getCurrentTime() >= region.start) {
     309      //   console.log("");
     310      } else {
     311         regionMouseEvent(region, false);
     312      }
     313   });
     314   wavesurfer.on('region-in', function(region) { regionMouseEvent(region, true); });
     315   wavesurfer.on('region-out', function(region) { regionMouseEvent(region, false); });
     316
     317   function regionMouseEvent(region, highlight) {
     318      var colour;
     319      if (highlight) {
     320         colour = "rgb(101, 116, 116)";
     321         regionEnter(region);
     322      } else {
     323         colour = "";
     324         regionLeave(region);
     325      }
     326      var regionIndex = region.id.replace("region","");
     327      var corrItem = corrItem = document.getElementById(itemType + regionIndex);
     328      corrItem.style.backgroundColor = colour;
     329   }
     330
     331   var chapterButton = document.getElementById("chapterButton");
     332   var backButton = document.getElementById("backButton");
     333   var playPauseButton = document.getElementById("playPauseButton");
     334   var forwardButton = document.getElementById("forwardButton");
     335   var muteButton = document.getElementById("muteButton");
     336   chapterButton.addEventListener("click", function() { toggleChapters(); });
     337   backButton.addEventListener("click", function() { wavesurfer.skipBackward(); });
     338   playPauseButton.addEventListener("click", function() { wavesurfer.playPause() });
     339   forwardButton.addEventListener("click", function() { wavesurfer.skipForward(); });
     340   muteButton.addEventListener("click", function() { wavesurfer.toggleMute(); });
     341
     342   var chapters = document.getElementById("chapters");
     343   chapters.style.height = "0px";
     344
     345   if (inputFile.endsWith("csv")) {
     346      itemType = "chapter";
     347      loadCSVFile(inputFile, ["speaker", "start", "end"]);
     348   } else if (inputFile.endsWith("json")) {
     349      itemType = "word";
     350      loadJSONFile(inputFile);
     351   } else {
     352      console.log("Filetype of " + inputFile + " not supported.")
     353   }
     354
     355   var interface_bootstrap_images = "interfaces/" + gs.xsltParams.interface_name + "/images/bootstrap/";
     356
     357   wavesurfer.on("play", function() { playPauseButton.src = interface_bootstrap_images + "pause.svg"; });
     358   wavesurfer.on("pause", function() { playPauseButton.src = interface_bootstrap_images + "play.svg"; });
     359   wavesurfer.on("mute", function(mute) {
     360      if (mute) muteButton.src = interface_bootstrap_images + "mute.svg";
     361      else muteButton.src = interface_bootstrap_images + "unmute.svg";
     362   });
     363
     364   document.querySelector('#slider').oninput = function () {
     365      wavesurfer.zoom(Number(this.value));
     366   };
     367
     368   var toggleChapters = function() {
     369      if (chapters.style.height == "0px") {
     370         chapters.style.height = "500px";
     371      } else {
     372         chapters.style.height = "0px";
     373      }
     374   }
     375
     376   function loadCSVFile(filename, manualHeader) { // based around: https://stackoverflow.com/questions/7431268/how-to-read-data-from-csv-file-using-javascript
     377      $.ajax({
     378         type: "GET",
     379         url: filename,
     380         dataType: "text",
     381      }).then(function(data) {
     382         
     383         var dataLines = data.split(/\r\n|\n/);
     384         var headers;
     385         var startIndex;
     386         uniqueSpeakers = [];
     387         speakerObjects = [];
     388
     389         if (manualHeader) {
     390            headers = manualHeader;
     391            startIndex = 0;
     392         } else {
     393            headers = dataLines[0].split(',');
     394            startIndex = 1;
     395         }
     396
     397         for (var i = startIndex; i < dataLines.length; i++) {
     398            var data = dataLines[i].split(',');
     399            if (data.length == headers.length) {
     400                  var item = {};
     401                  for (var j = 0; j < headers.length; j++) {
     402                     item[headers[j]] = data[j];
     403                     if (j == 0) {
     404                        if (!uniqueSpeakers.includes(data[j])) {
     405                              uniqueSpeakers.push(data[j]);
     406                        }
     407                     }
     408                  }
     409                  speakerObjects.push(item);
     410            }
     411         }
     412         populateChapters(speakerObjects);
     413      });
     414   }
     415
     416   function populateChapters(data) {
     417      // TODO: colorbrewer info
     418      colourbrewerset = colorbrewer.Set2[uniqueSpeakers.length];
     419      for (var i = 0; i < data.length; i++) {
     420         var chapter = document.createElement("div");
     421         chapter.id = "chapter" + i;
     422         chapter.classList.add("chapter");
     423         chapter.innerHTML = data[i].speaker + "<span class='speakerTime' id='" + "chapter" + i + "'>" + data[i].start + " - " + data[i].end + "s</span>";
     424         chapter.addEventListener("click", e => { chapterClicked(e.target.id) });
     425         chapter.addEventListener("mouseover", e => { chapterEnter(e.target.id) });
     426         chapter.addEventListener("mouseleave", e => { chapterLeave(e.target.id) });
     427         chapters.appendChild(chapter);
     428         wavesurfer.addRegion({
     429            id: "region" + i,
     430            start: data[i].start,
     431            end: data[i].end,
     432            drag: false,
     433            resize: false,
     434            // color: "rgba(255, 255, 255, 0.2)",
     435            color: colourbrewerset[uniqueSpeakers.indexOf(data[i].speaker)] + "66",
     436         });
     437      }
     438   }
     439
     440   function loadJSONFile(filename) {
     441      $.ajax({
     442         type: "GET",
     443         url: filename,
     444         dataType: "text",
     445      }).then(function(data){populateWords(JSON.parse(data))});
     446   }
     447
     448   function populateWords(data) {
     449      var transcription = data.transcription;
     450      var words = data.words;
     451      var wordContainer = document.createElement("div");
     452      wordContainer.id = "word-container";
     453      for (var i = 0; i < words.length; i++) {
     454         var word = document.createElement("span");
     455         word.id = "word" + i;
     456         word.classList.add("word");
     457         word.innerHTML = transcription.split(" ")[i];
     458         word.addEventListener("click", e => { wordClicked(data, e.target.id) });
     459         word.addEventListener("mouseover", e => { chapterEnter(e.target.id) });
     460         word.addEventListener("mouseleave", e => { chapterLeave(e.target.id) });
     461         wordContainer.appendChild(word);
     462         wavesurfer.addRegion({
     463            id: "region" + i,
     464            start: words[i].startTime,
     465            end: words[i].endTime,
     466            drag: false,
     467            resize: false,
     468            color: "rgba(255, 255, 255, 0.1)",
     469         });
     470      }
     471      chapters.appendChild(wordContainer);
     472   }
     473
     474   var chapterClicked = function(id) {
     475      var index = id.replace("chapter", "");
     476      var start = speakerObjects[index].start;
     477      var end = speakerObjects[index].end;
     478      // wavesurfer.play(start, end);
     479      wavesurfer.play(start);
     480   }
     481
     482   function wordClicked(data, id) {
     483      var index = id.replace("word", "");
     484      var start = data.words[index].startTime;
     485      var end = data.words[index].endTime;
     486      // wavesurfer.play(start, end);
     487      wavesurfer.play(start);
     488   }
     489
     490   function chapterEnter(id) {
     491      regionEnter(wavesurfer.regions.list["region" + id.replace(itemType, "")]);
     492   }
     493
     494   function chapterLeave(id) {
     495      regionLeave(wavesurfer.regions.list["region" + id.replace(itemType, "")]);
     496   }
     497
     498   function regionEnter(region) {
     499      setPrevColour(region);
     500      region.update({ color: "rgba(255, 255, 255, 0.35)" });
     501   }
     502
     503   function regionLeave(region) {
     504      if (itemType == "chapter") {
     505         region.update({ color: prevColour });
     506         // chapters.innerHTML = "";
     507         // wavesurfer.clearRegions();
     508         // populateChapters(speakerObjects);
     509
     510      } else {
     511         region.update({ color: "rgba(255, 255, 255, 0.1)" });
     512      }
     513   }
     514
     515   function setPrevColour(region) {
     516      var regionIndex = region.id.replace("region","");
     517      var corrItem = corrItem = document.getElementById(itemType + regionIndex);
     518      prevColour = colourbrewerset[uniqueSpeakers.indexOf(corrItem.firstChild.data)] + "66";
     519   }
     520}
Note: See TracChangeset for help on using the changeset viewer.