tutorial · 2026-04-29
UE5 Subtitles from a Dialogue DataTable: Sync Voice-Line Text to Audio
Drive on-screen subtitles straight from the same DataTable rows that play your NPC voice lines, with timing that follows the clip.
The text is already sitting next to the audio
If you want UE5 subtitles from a DataTable voice-line text setup, the good news is that you almost certainly do not need a second authoring step. In the Fantasy NPC Voices dialogue layer, every spoken line is one row of a 'DT_Dialogue' DataTable, and that row already carries both halves of what a subtitle needs: a 'ResponseText' string that is the exact words the actor speaks, and a 'VoiceAudio' field that points at the recording. The two are written by the same row, so they cannot drift apart.
Concretely, each row of 'DT_Dialogue' exposes the fields 'Name', 'DialogueName', 'ResponseText', 'CharacterName', 'EmotionalTone', 'ContextTags', 'NPCType' and 'VoiceAudio'. The audio reference is a 'TSoftObjectPtr<USoundWave>', which matters for timing: the clip is not in memory until you load it, and once it is, you can read its duration. 'ResponseText' is the line of dialogue verbatim, which means your subtitle is the transcript by construction rather than a hand-copied caption you have to keep in step.
Each character ships five DataTables (DT_Dialogue among them) built on five shared row schemas (UScriptStructs) that are byte-identical across all 21 archetypes in the pack, and the standalone single-character dialogue packs use that same DT_Dialogue row layout too. So the subtitle code you write once works for every speaker you ever drop in. That is the whole reason this is a three-step job and not a content pipeline.
Show the text the moment the clip plays
The cleanest place to raise a subtitle is the same function that already plays the line, so the caption and the audio start on the same frame. Whatever picks the row to speak should hand both fields to the UI at once.
1. Resolve the row you are about to play. You will typically already do this when you filter 'DT_Dialogue' by 'ContextTags' for the situation (for example a 'social/greeting' line) and pick one at random. Keep the row handle.
2. Read 'ResponseText' from that row and push it to your subtitle widget. A single bound 'Text' block on a screen-bottom widget is enough to start; style it later.
3. Load and play the clip. 'LoadSynchronous' on the 'VoiceAudio' soft pointer to get the 'USoundWave', then 'Play Sound 2D' for narration-style lines or 'Play Sound at Location' / a spatialised audio component for an NPC in the world.
Doing the text update first and the audio call second guarantees the caption is never late. Because 'ResponseText' is the spoken words, you do not need to author a separate caption track, and you side-step UE's built-in Subtitle system (the one tied to per-SoundWave 'SubtitleInfo') entirely — useful here because these clips ship as plain one-shot SoundWaves rather than carrying embedded subtitle data.
Dismiss it when the clip is actually finished
A fixed timer is the wrong way to clear a subtitle: lines in this pack range from one-word barks to paragraph-length story beats, so any single hold duration will either cut long lines off or leave short ones lingering. Drive the dismissal off the audio instead, because the clips are one-shot with no looping — when the sound ends, the line is over, full stop.
The most reliable approach is to spawn the line through an audio component rather than the fire-and-forget 'Play Sound' nodes, then bind the component's 'OnAudioFinished' event to a function that hides the subtitle widget. The text stays up for exactly as long as the voice is speaking and disappears on completion, with no guesswork and no magic numbers.
If you prefer not to manage components, you can read the clip length up front. After 'LoadSynchronous', call 'Get Duration' on the 'USoundWave' and set a timer for that many seconds to clear the caption. That gives you a single hold value that is correct per line, and it also lets you add a small fixed tail (a quarter-second or so) so the words do not vanish on the very last syllable. Either way the rule is the same: let the clip's own length decide, never a global constant.
Plan for localisation before you ship
Subtitles are where a single-language voice pack quietly becomes multi-language text, so it is worth setting up correctly before the strings multiply. 'ResponseText' is a plain 'FString' on the row, which is fine for English-only projects, but if you intend to localise you should route the displayed caption through UE's text-localisation system rather than binding the raw string directly to the widget.
The pragmatic pattern is to use the row's 'Name' key (the FName that identifies the row) as a stable string-table key. Show the localised entry for that key when one exists and fall back to the row's 'ResponseText' when it does not. The English line then doubles as both the shipped subtitle and the default fallback, and your translators work against the same row identifiers your gameplay code already uses to pick lines.
Two pack-specific notes shape the work. First, this is a sizeable corpus — 12,111 dialogue lines across the complete bundle (12,904 voiced clips once the 793 voice-FX lines are counted) — so localisation is a real budgeting decision; you will likely caption the story-critical 'ContextTags' first and leave ambient barks last. Second, the audio is voiced in one language only; subtitles let players read a translation while still hearing the original performance, which for many fantasy titles is exactly the desired effect.
The voice line text approach to UE5 subtitles scales the moment you add more speakers, because every archetype shares the same 'DT_Dialogue' schema. Add the Bard, Assassin or Blacksmith pack and your existing 'ResponseText'-to-widget path captions them with zero new code.
Two ways to time the subtitle dismissal
| Approach | How it ends the subtitle | Best for |
|---|---|---|
| Audio component + OnAudioFinished | Event fires when the SoundWave stops; hide the widget in the handler | Spatialised NPC lines you already spawn via a component |
| Get Duration + timer | Read clip length after LoadSynchronous, set a timer to clear the caption | Fire-and-forget 2D narration where you want a small fixed tail |
Both rely on the clips being one-shot SoundWaves with a finite duration; pick the row first, then the line drives its own hold time.
FAQ
How do I get UE5 subtitles from a DataTable voice-line text field?
Read the 'ResponseText' string from the same 'DT_Dialogue' row whose 'VoiceAudio' clip you are about to play, push it to a subtitle widget, then play the sound. Because the text and the audio reference live on one row, the caption is the verbatim transcript and the two cannot fall out of sync.
How long should each subtitle stay on screen?
For exactly as long as the clip plays. The lines vary from one-word barks to paragraphs, so a fixed duration is wrong. Either bind an audio component's 'OnAudioFinished' to hide the widget, or call 'Get Duration' on the loaded 'USoundWave' and set a timer for that length.
Do I need UE's built-in Subtitle system or SoundWave SubtitleInfo?
No. These ship as plain one-shot SoundWaves without embedded subtitle data, so driving the caption from the row's 'ResponseText' is simpler and gives you full control over styling and timing without touching per-asset SubtitleInfo.
Will the same subtitle code work for other characters?
Yes. All 21 archetypes in Fantasy NPC Voices, and the standalone Bard, Assassin and Blacksmith packs, share the identical 'DT_Dialogue' schema with 'ResponseText' and 'VoiceAudio'. Write the caption path once and every speaker is covered.
Can I localise the subtitles?
Yes. Use the row's 'Name' FName as a string-table key, show the localised entry when present and fall back to 'ResponseText' otherwise. The audio stays in its recorded language while players read a translated caption.
Fantasy NPC Voices
The complete fantasy voice megabundle: roughly 33 hours of dialogue across 13,668 voiced WAVs at 44.1 kHz — paladins, vampires, witches, wizards, bards, goblins, necromancers and more. One library to voice an entire RPG cast.