Overview
TheVoiceActivityDetector class is an abstract base class for implementing Voice Activity Detection (VAD). VAD is used to identify segments of audio that contain human speech versus silence or background noise. WhisperKit uses VAD to intelligently chunk long audio files for more efficient transcription.
Class Definition
Initializer
Int
default:"16000"
Sample rate of the audio signal in Hz
Int
Length of each analysis frame in samples
Int
default:"0"
Number of samples overlapping between consecutive frames
Properties
Int
The sample rate of the audio signal in samples per second (typically 16000 Hz for WhisperKit)
Int
The length of each analysis frame in samples
Int
The number of samples overlapping between consecutive frames. Useful for catching speech at frame boundaries.
Methods
voiceActivity(in:)
Analyzes audio waveform to detect voice activity. Must be implemented by subclasses.[Float]
Array of audio samples to analyze
[Bool]
Array where
true indicates voice activity and false indicates silence. Each element corresponds to one frame.voiceActivityAsync(in:)
Async version of voice activity detection.[Float]
Array of audio samples to analyze
[Bool]
Array indicating voice activity per frame
calculateActiveChunks(in:)
Identifies continuous segments of audio containing voice activity.[Float]
Array of audio samples
[(startIndex: Int, endIndex: Int)]
Array of tuples containing start and end sample indices for each active segment
voiceActivityIndexToAudioSampleIndex(_:)
Converts a voice activity frame index to an audio sample index.Int
Voice activity frame index
Int
Corresponding audio sample index
voiceActivityIndexToSeconds(_:)
Converts a voice activity frame index to time in seconds.Int
Voice activity frame index
Float
Corresponding time in seconds
findLongestSilence(in:)
Finds the longest continuous period of silence.[Bool]
Voice activity detection results
(startIndex: Int, endIndex: Int)?
Start and end indices of the longest silence, or nil if no silence found
voiceActivityClipTimestamps(in:)
Generates timestamp pairs for active audio segments.[Float]
Flat array of timestamps: [start1, end1, start2, end2, …]
calculateNonSilentSeekClips(in:)
Calculates seek positions for non-silent segments.[(start: Int, end: Int)]
Array of seek clip start/end positions in samples
calculateSeekTimestamps(in:)
Calculates timestamp pairs for seeking through active segments.[(startTime: Float, endTime: Float)]
Array of start/end timestamp pairs in seconds
Built-in Implementation: EnergyVAD
WhisperKit includes a built-in energy-based VAD implementation:How EnergyVAD Works
EnergyVAD detects voice activity by:- Dividing audio into frames
- Calculating RMS energy for each frame
- Comparing energy against a threshold
- Frames above threshold are marked as containing voice
Custom Implementation
To create a custom VAD, subclassVoiceActivityDetector and implement voiceActivity(in:):
Example Usage
Basic Voice Activity Detection
Find Active Segments
Use VAD with WhisperKit
Visualize Voice Activity
Find Silence for Split Points
Custom Energy Threshold
Process Live Audio with VAD
Best Practices
- Frame Length Selection: Use 20-100ms frames (320-1600 samples at 16kHz). Shorter frames = more responsive but noisier.
-
Threshold Tuning: Adjust energy threshold based on your audio:
- Clean recordings: 0.01-0.02
- Noisy environments: 0.03-0.05
- Test with representative samples
- Overlap for Continuity: Use frame overlap (10-20ms) to avoid missing speech at frame boundaries.
-
Post-Processing: Apply smoothing to reduce false positives:
-
Chunking Strategy: When using
.vadchunking strategy with WhisperKit, ensure your VAD is tuned to avoid creating too many tiny segments.