The Voice Manager Subsystem is a game instance subsystem for managing voice-over playback in Unreal Engine 5.7. It provides sophisticated control over VO playback through a double priority system, automatic queueing, and intelligent interruption handling.
The Voice Manager is part of the Demute Tech Audio Toolkit and supports two audio backends:
Link to the toolkit installation instructions
Access Voice Over Manager settings at Edit → Project Settings → Plugins → Voice Over Manager.

Make sure to correctly set your audio backend depending on whether you are using Native Unreal audio, or Fmod.
AudioBackend (enum)
VoiceOverDataTables (array of Data Table references)
VODelayTime (float, default: 1.0)
VOAllowFinishTime (float, default: 1.0)
The FMOD backend requires the FMOD Studio Plugin for Unreal Engine.
IMPORTANT: For the Voice Manager to work with FMOD, your FMOD events must include a Programmer Sound instrument, and the sound bank must contain an Audio Table:

No external prerequisites required! The Native backend uses Unreal Engine's built-in audio system.
Voice-over data is all the information (such as each VO's priority) that the system requires to function.
Voice-Over data can be organized in two ways:
Data Tables (Recommended for most use cases)

Data Assets (For special cases)
PlayUnregisteredVO methods
Important: You must use backend-specific data structures:
VOInfoTableRow_FMOD and VOInfo_FMODVOInfoTableRow_Native and VOInfo_NativeCreating and configuring voice-over data for the FMOD Studio backend.
DT_VoiceOvers_FMOD_Combat)Row Name (FName)
PlayRegisteredVO2D, PlayRegisteredVOAtLocation, PlayRegisteredVOAttachedRow Editor window and must be done by double-clicking on the Row Name column for the corresponding rowPlayer_Damage_Heavy, Boss_Taunt_01FMODEvent (UFMODEvent reference)
LocalizationKeys (Array of FString)
NoRepeats to avoid repetition"VO_Player_Damage_01", "VO_Boss_Taunt_Variant_A"For use with PlayUnregisteredVO methods, you can create standalone VOInfo Data Assets instead of using data tables.
Steps to Create:
VO_FMOD_Special_Event)Configuring Properties:
VOInfo_FMOD Data Assets have the same properties as data table rows:
Creating and configuring voice-over data for the Native UE Audio backend.
DT_VoiceOvers_Native_Combat)Row Name (FName)
PlayRegisteredVO2D, PlayRegisteredVOAtLocation, PlayRegisteredVOAttachedRow Editor window and must be done by double-clicking on the Row Name column for the corresponding rowPlayer_Damage_Heavy, Boss_Taunt_01SoundWaves (Array of USoundWave references)
NoRepeats to avoid repetitionSW_Player_Damage_01, SW_Boss_Taunt_Variant_AFor use with PlayUnregisteredVO methods, you can create standalone VOInfo Data Assets instead of using data tables.
Steps to Create:
VO_Native_Special_Event)Configuring Properties:
VOInfo_Native Data Assets have the same properties as data table rows:
The following properties are available in both FMOD and Native backends and work identically.
TriggerPriority (int32, default: 0)
PlaybackPriority of currently playing VOsPlaybackPriority (int32, default: 0)
bToQueue (bool, default: false)
bQueueOnInterrupt (bool, default: false)
CooldownTime (float, default: 0.0)
NoRepeats (int32, default: 0)
VOTags (Gameplay Tag Container, optional)
VO.Combat.Death, VO.UI.ButtonClickDisplayName (Text, optional)
Use Data Tables when:
Use Data Tables when:
Use VOInfo Data Assets when:
In Blueprint: Use Get Voice Over Manager Subsystem node

In C++:
#include "VoiceOverManagerSubsystem.h"
UVoiceOverManagerSubsystem* VOSubsystem =
GetGameInstance()->GetSubsystem<UVoiceOverManagerSubsystem>();The Voice Manager provides a consistent API for playing voice-overs regardless of which backend you're using. All play methods work identically for both FMOD and Native backends.
Plays a VO by its Row Name from a loaded data table in 2D (non-spatialized).
Parameters:
ID (FName): The Row Name of the VO in your data tableReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VO ID not found in data tables; valid handle with Rejected state if on cooldown)
Blueprint Example:

C++ Example:
UVOPlaybackHandle* Handle = VOSubsystem->PlayRegisteredVO2D(FName("Player_Damage_Heavy"));Backend Notes:
Plays a VOInfo Data Asset directly without using data tables, in 2D.
Parameters:
VOInfo (UVOInfo*): A VOInfo_FMOD or VOInfo_Native Data Asset referenceReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VOInfo parameter is null; valid handle with Rejected state if on cooldown)
Backend Notes:
Plays a VO at a specific world location with 3D spatialization.
Parameters:
ID (FName): The Row Name of the VO in your data tableLocation (FVector): World location where the sound should playReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VO ID not found in data tables; valid handle with Rejected state if on cooldown)
Blueprint Example:

C++ Example:
UVOPlaybackHandle* Handle = VOSubsystem->PlayRegisteredVOAtLocation(
FName("Enemy_Death_Scream"),
EnemyActor->GetActorLocation()
);Backend Notes:
Plays a VOInfo Data Asset at a specific world location.
Parameters:
VOInfo (UVOInfo*): A VOInfo_FMOD or VOInfo_Native Data Asset referenceLocation (FVector): World location where the sound should playReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VOInfo parameter is null; valid handle with Rejected state if on cooldown)
Plays a VO attached to a scene component, following its movement.
Parameters:
ID (FName): The Row Name of the VO in your data tableAttachComponent (USceneComponent*): Component to attach the audio toReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VO ID not found in data tables; valid handle with Rejected state if on cooldown)
Blueprint Example:

C++ Example:
UVOPlaybackHandle* Handle = VOSubsystem->PlayRegisteredVOAttached(
FName("Character_Breathing"),
HeadComponent
);Backend Notes:
Plays a VOInfo Data Asset attached to a scene component.
Parameters:
VOInfo (UVOInfo*): A VOInfo_FMOD or VOInfo_Native Data Asset referenceAttachComponent (USceneComponent*): Component to attach the audio toReturns: UVOPlaybackHandle* - Handle for tracking this playback (null if VOInfo parameter is null; valid handle with Rejected state if on cooldown)
All play methods return a UVOPlaybackHandle* object that allows you to track and monitor the playback of a specific VO instance.
A VOPlaybackHandle is a Blueprint-friendly object that provides:
The VOPlaybackHandle works identically for both FMOD and Native backends.
All handle methods are available in both c++ and blueprints.
When is a null handle returned?
Should only happen if there is a problem with the setup.
When is a valid handle with Rejected state returned?
Subscribe to delegates to be notified when playback starts or finishes:
Blueprint: Use the Assign On nodes to get a delegate to when the vo starts playing, or when it finishes playing.

C++:
UVOPlaybackHandle* Handle = VOSubsystem->PlayRegisteredVO2D(FName("MyVO"));
if (Handle)
{
Handle->OnVOStarted.AddDynamic(this, &UMyClass::HandleVOStarted);
Handle->OnVOFinished.AddDynamic(this, &UMyClass::HandleVOFinished);
}
// Delegate handler functions
void UMyClass::HandleVOStarted(UVOPlaybackHandle* Handle)
{
UE_LOG(LogTemp, Log, TEXT("VO Started: %s"), *Handle->GetDisplayName());
}
void UMyClass::HandleVOFinished(UVOPlaybackHandle* Handle)
{
UE_LOG(LogTemp, Log, TEXT("VO Finished: %s"), *Handle->GetDisplayName());
}Available Methods:
float GetCurrentPlaytime - current playback time in secondsfloat GetTotalDuration - total duration of file in secondsfloat GetTimeRemaining - amount of play time remaining in secondsfloat GetPlaybackProgress - 0 to 1, with 0 being unstarted and 1 being finishedC++ Example:
if (Handle && Handle->IsPlaying())
{
float Progress = Handle->GetPlaybackProgress(); // 0.0 to 1.0
float Remaining = Handle->GetTimeRemaining(); // Seconds
UE_LOG(LogTemp, Log, TEXT("VO Progress: %.1f%% (%.1fs remaining)"),
Progress * 100.0f, Remaining);
}Available Methods:
bool IsPlaying() - True if currently playing audiobool IsQueued() - True if queued and waiting to playbool IsFinished() - True if playback completed or was interruptedbool WasRejected() - True if VO was rejected (cooldown, invalid, etc.)EVOPlaybackState GetPlaybackState() - Returns current state enum (Rejected, Queued, Playing, Finished)State Lifecycle:
Null Handle (ID not found, null VOInfo)
Valid Handle:
→ Rejected (on cooldown / lower priority & not set to queue)
→ Queued → Playing → Finished (completed)
↘ Finished (interrupted)
→ Playing → Finished (if played immediately)Available Methods:
EVOSpatializationMode GetSpatializationMode() - Returns VO2D, VOLocation, or VOAttached (enum)FVector GetPlaybackLocation() - World location (only valid when mode is VOLocation)USceneComponent* GetAttachedComponent() - Attached component (only valid when mode is VOAttached)UVOInfoBase* GetVOInfo() - The VOInfo being played (even if using registered vo, will return a VOInfo that represents the row information)FString GetDisplayName() - Display name for debuggingAll these methods are available to the subsystem.
Loads a data table at runtime and assigns it a unique ID.
Parameters:
TableID (FName): Unique identifier for this tableDataTable (UDataTable*): The data table to loadReturns: bool - True if loaded successfully
Notes:
VOInfoTableRow_FMOD structureVOInfoTableRow_Native structureUnloads a dynamically loaded data table.
Parameters:
TableID (FName): The ID used when loading the tableReturns: bool - True if unloaded successfully
Notes:
Checks if a data table with the given ID is currently loaded.
Parameters:
TableID (FName): The ID to checkReturns: bool - True if the table is loaded
All these methods are available to the subsystem.
Checks if any VO is currently playing.
Returns: bool - True if audio is playing
Immediately stops the currently playing VO.
Returns: bool - True if playback was stopped successfully
Notes:
bQueueOnInterrupt behaviorVODelayTimeEmpties the entire VO queue without affecting current playback.
Returns: bool - True if queue was cleared successfully
The Voice Manager uses a double priority system to provide fine-grained control over interruption and queueing. This system works identically for both FMOD and Native backends.
PlaybackPriority of the currently playing VO.Logic:
TriggerPriority > PlaybackPriority of current VO:VOAllowFinishTime)bQueueOnInterrupt set to true)VOAllowFinishTime)TriggerPriority ≤ PlaybackPriority of current VO:bToQueue is true)bToQueue is false)
The queue uses priority-based FIFO ordering:
VODelayTime project settingExample Queue Processing:
Queue State:
[Priority 50] VO_A
[Priority 75] VO_B
[Priority 50] VO_C
[Priority 25] VO_D
Playback Order:
1. VO_B (priority 75)
2. VO_A (priority 50, added before VO_C)
3. VO_C (priority 50, added after VO_A)
4. VO_D (priority 25)C++ API Quick Reference// 2D Audio (Non-Spatialized)
UVOPlaybackHandle* PlayRegisteredVO2D(FName ID);
UVOPlaybackHandle* PlayUnregisteredVO2D(UVOInfo* VOInfo);
// 3D at Location (Spatialized at fixed position)
UVOPlaybackHandle* PlayRegisteredVOAtLocation(FName ID, FVector Location);
UVOPlaybackHandle* PlayUnregisteredVOAtLocation(UVOInfo* VOInfo, FVector Location);
// 3D Attached (Spatialized and follows component)
UVOPlaybackHandle* PlayRegisteredVOAttached(FName ID, USceneComponent* AttachComponent);
UVOPlaybackHandle* PlayUnregisteredVOAttached(UVOInfo* VOInfo, USceneComponent* AttachComponent);
// Return values:
// - Null: VO ID not found (Registered methods) or VOInfo param was null (Unregistered methods)
// - Valid handle with Rejected state: On cooldown or rejected due to priority
// - Valid handle with Queued state: Queued to play later
// - Valid handle with Playing state: Started playing immediately// Load a data table at runtime
bool LoadDataTable(FName TableID, UDataTable* DataTable);
// Unload a dynamically loaded data table
bool UnloadDataTable(FName TableID);
// Check if a table is loaded
bool IsDataTableLoaded(FName TableID) const;// Check if audio is playing
bool IsPlaying() const;
// Stop current playback
bool StopPlayback();
// Clear the queue
bool ClearQueue();