From e390bda83ebf5a2b538cb306ca0c1feb44244a7e Mon Sep 17 00:00:00 2001 From: Jose B Date: Fri, 18 Aug 2023 14:12:48 -0500 Subject: [PATCH] initial TS implementation --- www/app/lib/custom-plugins/record.js | 129 ------------------ .../record.ts} | 3 +- www/app/lib/custom-plugins/regions.js | 12 -- www/app/lib/custom-plugins/regions.ts | 18 +++ www/app/transcripts/custom-plugins/record.js | 129 ------------------ www/app/transcripts/custom-plugins/regions.js | 12 -- 6 files changed, 19 insertions(+), 284 deletions(-) delete mode 100644 www/app/lib/custom-plugins/record.js rename www/app/lib/{CustomRecordPlugin.js => custom-plugins/record.ts} (95%) delete mode 100644 www/app/lib/custom-plugins/regions.js create mode 100644 www/app/lib/custom-plugins/regions.ts delete mode 100644 www/app/transcripts/custom-plugins/record.js delete mode 100644 www/app/transcripts/custom-plugins/regions.js diff --git a/www/app/lib/custom-plugins/record.js b/www/app/lib/custom-plugins/record.js deleted file mode 100644 index ab99170f..00000000 --- a/www/app/lib/custom-plugins/record.js +++ /dev/null @@ -1,129 +0,0 @@ -// Override the startRecording method so we can pass the desired stream -// Checkout: https://github.com/katspaugh/wavesurfer.js/blob/fa2bcfe/src/plugins/record.ts - -import RecordPlugin from "wavesurfer.js/dist/plugins/record"; - -const MIME_TYPES = [ - "audio/webm", - "audio/wav", - "audio/mpeg", - "audio/mp4", - "audio/mp3", -]; -const findSupportedMimeType = () => - MIME_TYPES.find((mimeType) => MediaRecorder.isTypeSupported(mimeType)); - -class CustomRecordPlugin extends RecordPlugin { - static create(options) { - return new CustomRecordPlugin(options || {}); - } - render(stream) { - if (!this.wavesurfer) return () => undefined; - - const container = this.wavesurfer.getWrapper(); - const canvas = document.createElement("canvas"); - canvas.width = container.clientWidth; - canvas.height = container.clientHeight; - canvas.style.zIndex = "10"; - container.appendChild(canvas); - - const canvasCtx = canvas.getContext("2d"); - const audioContext = new AudioContext(); - const source = audioContext.createMediaStreamSource(stream); - const analyser = audioContext.createAnalyser(); - analyser.fftSize = 2 ** 5; - source.connect(analyser); - const bufferLength = analyser.frequencyBinCount; - const dataArray = new Uint8Array(bufferLength); - - let animationId, previousTimeStamp; - const DATA_SIZE = 128.0; - const BUFFER_SIZE = 2 ** 8; - const dataBuffer = new Array(BUFFER_SIZE).fill(DATA_SIZE); - - const drawWaveform = (timeStamp) => { - if (!canvasCtx) return; - - analyser.getByteTimeDomainData(dataArray); - canvasCtx.clearRect(0, 0, canvas.width, canvas.height); - canvasCtx.fillStyle = "#cc3347"; - - if (previousTimeStamp === undefined) { - previousTimeStamp = timeStamp; - dataBuffer.push(Math.min(...dataArray)); - dataBuffer.splice(0, 1); - } - const elapsed = timeStamp - previousTimeStamp; - if (elapsed > 10) { - previousTimeStamp = timeStamp; - dataBuffer.push(Math.min(...dataArray)); - dataBuffer.splice(0, 1); - } - - // Drawing - const sliceWidth = canvas.width / dataBuffer.length; - let x = 0; - - for (let i = 0; i < dataBuffer.length; i++) { - const y = (canvas.height * dataBuffer[i]) / (2 * DATA_SIZE); - const sliceHeight = - ((1 - canvas.height) * dataBuffer[i]) / DATA_SIZE + canvas.height; - - canvasCtx.fillRect(x, y, (sliceWidth * 2) / 3, sliceHeight); - x += sliceWidth; - } - - animationId = requestAnimationFrame(drawWaveform); - }; - - drawWaveform(); - - return () => { - if (animationId) { - cancelAnimationFrame(animationId); - } - - if (source) { - source.disconnect(); - source.mediaStream.getTracks().forEach((track) => track.stop()); - } - - if (audioContext) { - audioContext.close(); - } - - canvas?.remove(); - }; - } - startRecording(stream) { - this.preventInteraction(); - this.cleanUp(); - - const onStop = this.render(stream); - const mediaRecorder = new MediaRecorder(stream, { - mimeType: this.options.mimeType || findSupportedMimeType(), - audioBitsPerSecond: this.options.audioBitsPerSecond, - }); - const recordedChunks = []; - - mediaRecorder.addEventListener("dataavailable", (event) => { - if (event.data.size > 0) { - recordedChunks.push(event.data); - } - }); - - mediaRecorder.addEventListener("stop", () => { - onStop(); - this.loadBlob(recordedChunks, mediaRecorder.mimeType); - this.emit("stopRecording"); - }); - - mediaRecorder.start(); - - this.emit("startRecording"); - - this.mediaRecorder = mediaRecorder; - } -} - -export default CustomRecordPlugin; diff --git a/www/app/lib/CustomRecordPlugin.js b/www/app/lib/custom-plugins/record.ts similarity index 95% rename from www/app/lib/CustomRecordPlugin.js rename to www/app/lib/custom-plugins/record.ts index ab99170f..aa85a812 100644 --- a/www/app/lib/CustomRecordPlugin.js +++ b/www/app/lib/custom-plugins/record.ts @@ -1,5 +1,4 @@ -// Override the startRecording method so we can pass the desired stream -// Checkout: https://github.com/katspaugh/wavesurfer.js/blob/fa2bcfe/src/plugins/record.ts +// Source code: https://github.com/katspaugh/wavesurfer.js/blob/fa2bcfe/src/plugins/record.ts import RecordPlugin from "wavesurfer.js/dist/plugins/record"; diff --git a/www/app/lib/custom-plugins/regions.js b/www/app/lib/custom-plugins/regions.js deleted file mode 100644 index 528e99a3..00000000 --- a/www/app/lib/custom-plugins/regions.js +++ /dev/null @@ -1,12 +0,0 @@ -import RegionsPlugin from "wavesurfer.js/dist/plugins/regions"; - -class CustomRegionsPlugin extends RegionsPlugin { - static create(options) { - return new CustomRegionsPlugin(options); - } - avoidOverlapping(region) { - // Prevent overlapping regions - } -} - -export default CustomRegionsPlugin; diff --git a/www/app/lib/custom-plugins/regions.ts b/www/app/lib/custom-plugins/regions.ts new file mode 100644 index 00000000..12fb7012 --- /dev/null +++ b/www/app/lib/custom-plugins/regions.ts @@ -0,0 +1,18 @@ +// Source code: https://github.com/katspaugh/wavesurfer.js/blob/fa2bcfe/src/plugins/regions.ts + +import RegionsPlugin, { + RegionsPluginOptions, +} from "wavesurfer.js/dist/plugins/regions"; + +class CustomRegionsPlugin extends RegionsPlugin { + public static create(options?: RegionsPluginOptions) { + return new RegionsPlugin(options); + } + + constructor(options?: RegionsPluginOptions) { + super(options); + this["avoidOverlapping"] = () => {}; + } +} + +export default CustomRegionsPlugin; diff --git a/www/app/transcripts/custom-plugins/record.js b/www/app/transcripts/custom-plugins/record.js deleted file mode 100644 index ab99170f..00000000 --- a/www/app/transcripts/custom-plugins/record.js +++ /dev/null @@ -1,129 +0,0 @@ -// Override the startRecording method so we can pass the desired stream -// Checkout: https://github.com/katspaugh/wavesurfer.js/blob/fa2bcfe/src/plugins/record.ts - -import RecordPlugin from "wavesurfer.js/dist/plugins/record"; - -const MIME_TYPES = [ - "audio/webm", - "audio/wav", - "audio/mpeg", - "audio/mp4", - "audio/mp3", -]; -const findSupportedMimeType = () => - MIME_TYPES.find((mimeType) => MediaRecorder.isTypeSupported(mimeType)); - -class CustomRecordPlugin extends RecordPlugin { - static create(options) { - return new CustomRecordPlugin(options || {}); - } - render(stream) { - if (!this.wavesurfer) return () => undefined; - - const container = this.wavesurfer.getWrapper(); - const canvas = document.createElement("canvas"); - canvas.width = container.clientWidth; - canvas.height = container.clientHeight; - canvas.style.zIndex = "10"; - container.appendChild(canvas); - - const canvasCtx = canvas.getContext("2d"); - const audioContext = new AudioContext(); - const source = audioContext.createMediaStreamSource(stream); - const analyser = audioContext.createAnalyser(); - analyser.fftSize = 2 ** 5; - source.connect(analyser); - const bufferLength = analyser.frequencyBinCount; - const dataArray = new Uint8Array(bufferLength); - - let animationId, previousTimeStamp; - const DATA_SIZE = 128.0; - const BUFFER_SIZE = 2 ** 8; - const dataBuffer = new Array(BUFFER_SIZE).fill(DATA_SIZE); - - const drawWaveform = (timeStamp) => { - if (!canvasCtx) return; - - analyser.getByteTimeDomainData(dataArray); - canvasCtx.clearRect(0, 0, canvas.width, canvas.height); - canvasCtx.fillStyle = "#cc3347"; - - if (previousTimeStamp === undefined) { - previousTimeStamp = timeStamp; - dataBuffer.push(Math.min(...dataArray)); - dataBuffer.splice(0, 1); - } - const elapsed = timeStamp - previousTimeStamp; - if (elapsed > 10) { - previousTimeStamp = timeStamp; - dataBuffer.push(Math.min(...dataArray)); - dataBuffer.splice(0, 1); - } - - // Drawing - const sliceWidth = canvas.width / dataBuffer.length; - let x = 0; - - for (let i = 0; i < dataBuffer.length; i++) { - const y = (canvas.height * dataBuffer[i]) / (2 * DATA_SIZE); - const sliceHeight = - ((1 - canvas.height) * dataBuffer[i]) / DATA_SIZE + canvas.height; - - canvasCtx.fillRect(x, y, (sliceWidth * 2) / 3, sliceHeight); - x += sliceWidth; - } - - animationId = requestAnimationFrame(drawWaveform); - }; - - drawWaveform(); - - return () => { - if (animationId) { - cancelAnimationFrame(animationId); - } - - if (source) { - source.disconnect(); - source.mediaStream.getTracks().forEach((track) => track.stop()); - } - - if (audioContext) { - audioContext.close(); - } - - canvas?.remove(); - }; - } - startRecording(stream) { - this.preventInteraction(); - this.cleanUp(); - - const onStop = this.render(stream); - const mediaRecorder = new MediaRecorder(stream, { - mimeType: this.options.mimeType || findSupportedMimeType(), - audioBitsPerSecond: this.options.audioBitsPerSecond, - }); - const recordedChunks = []; - - mediaRecorder.addEventListener("dataavailable", (event) => { - if (event.data.size > 0) { - recordedChunks.push(event.data); - } - }); - - mediaRecorder.addEventListener("stop", () => { - onStop(); - this.loadBlob(recordedChunks, mediaRecorder.mimeType); - this.emit("stopRecording"); - }); - - mediaRecorder.start(); - - this.emit("startRecording"); - - this.mediaRecorder = mediaRecorder; - } -} - -export default CustomRecordPlugin; diff --git a/www/app/transcripts/custom-plugins/regions.js b/www/app/transcripts/custom-plugins/regions.js deleted file mode 100644 index 528e99a3..00000000 --- a/www/app/transcripts/custom-plugins/regions.js +++ /dev/null @@ -1,12 +0,0 @@ -import RegionsPlugin from "wavesurfer.js/dist/plugins/regions"; - -class CustomRegionsPlugin extends RegionsPlugin { - static create(options) { - return new CustomRegionsPlugin(options); - } - avoidOverlapping(region) { - // Prevent overlapping regions - } -} - -export default CustomRegionsPlugin;