From 4673c666424f751364817dd7d74ef9adbd3c19ba Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Mon, 12 Aug 2024 07:33:33 +0200 Subject: [PATCH] Feat: [Record] continuous waveform mode (#3818) * Feat: [Record] continuous waveform mode * Fix: set position to the latest sample * Bar width --- examples/record.js | 37 +++++++++++++++++-- src/plugins/record.ts | 85 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 17 deletions(-) diff --git a/examples/record.js b/examples/record.js index 1eeee6470..b7d6bef08 100644 --- a/examples/record.js +++ b/examples/record.js @@ -5,12 +5,15 @@ import RecordPlugin from 'wavesurfer.js/dist/plugins/record.esm.js' let wavesurfer, record let scrollingWaveform = false +let continuousWaveform = true const createWaveSurfer = () => { - // Create an instance of WaveSurfer + // Destroy the previous wavesurfer instance if (wavesurfer) { wavesurfer.destroy() } + + // Create a new Wavesurfer instance wavesurfer = WaveSurfer.create({ container: '#mic', waveColor: 'rgb(200, 0, 200)', @@ -18,7 +21,15 @@ const createWaveSurfer = () => { }) // Initialize the Record plugin - record = wavesurfer.registerPlugin(RecordPlugin.create({ scrollingWaveform, renderRecordedAudio: false })) + record = wavesurfer.registerPlugin( + RecordPlugin.create({ + renderRecordedAudio: false, + scrollingWaveform, + continuousWaveform, + continuousWaveformDuration: 30, // optional + }), + ) + // Render recorded audio record.on('record-end', (blob) => { const container = document.querySelector('#recordings') @@ -114,8 +125,22 @@ recButton.onclick = () => { pauseButton.style.display = 'inline' }) } -document.querySelector('input[type="checkbox"]').onclick = (e) => { + +document.querySelector('#scrollingWaveform').onclick = (e) => { scrollingWaveform = e.target.checked + if (continuousWaveform && scrollingWaveform) { + continuousWaveform = false + document.querySelector('#continuousWaveform').checked = false + } + createWaveSurfer() +} + +document.querySelector('#continuousWaveform').onclick = (e) => { + continuousWaveform = e.target.checked + if (continuousWaveform && scrollingWaveform) { + scrollingWaveform = false + document.querySelector('#scrollingWaveform').checked = false + } createWaveSurfer() } @@ -135,7 +160,11 @@ createWaveSurfer() - + + + + +
00:00
diff --git a/src/plugins/record.ts b/src/plugins/record.ts index 8634e2585..7664768bd 100644 --- a/src/plugins/record.ts +++ b/src/plugins/record.ts @@ -4,18 +4,23 @@ import BasePlugin, { type BasePluginEvents } from '../base-plugin.js' import Timer from '../timer.js' +import type { WaveSurferOptions } from '../wavesurfer.js' export type RecordPluginOptions = { /** The MIME type to use when recording audio */ mimeType?: MediaRecorderOptions['mimeType'] /** The audio bitrate to use when recording audio, defaults to 128000 to avoid a VBR encoding. */ audioBitsPerSecond?: MediaRecorderOptions['audioBitsPerSecond'] - /** Whether to render the recorded audio, true by default */ + /** Whether to render the recorded audio at the end, true by default */ renderRecordedAudio?: boolean /** Whether to render the scrolling waveform, false by default */ scrollingWaveform?: boolean /** The duration of the scrolling waveform window, defaults to 5 seconds */ scrollingWaveformWindow?: number + /** Accumulate and render the waveform data as the audio is being recorded, false by default */ + continuousWaveform?: boolean + /** The duration of the continuous waveform, in seconds */ + continuousWaveformDuration?: number /** The timeslice to use for the media recorder */ mediaRecorderTimeslice?: number } @@ -26,12 +31,17 @@ export type RecordPluginDeviceOptions = { } export type RecordPluginEvents = BasePluginEvents & { + /** Fires when the recording starts */ 'record-start': [] + /** Fires when the recording is paused */ 'record-pause': [blob: Blob] + /** Fires when the recording is resumed */ 'record-resume': [] + /* When the recording stops, either by calling stopRecording or when the media recorder stops */ 'record-end': [blob: Blob] /** Fires continuously while recording */ 'record-progress': [duration: number] + /** On every new recorded chunk */ 'record-data-available': [blob: Blob] } @@ -42,6 +52,7 @@ type MicStream = { const DEFAULT_BITS_PER_SECOND = 128000 const DEFAULT_SCROLLING_WAVEFORM_WINDOW = 5 +const FPS = 60 const MIME_TYPES = ['audio/webm', 'audio/wav', 'audio/mpeg', 'audio/mp4', 'audio/mp3'] const findSupportedMimeType = () => MIME_TYPES.find((mimeType) => MediaRecorder.isTypeSupported(mimeType)) @@ -51,7 +62,7 @@ class RecordPlugin extends BasePlugin