Repository navigation
Conversation
Players talk over the existing game connection, no separate program or port. Clients send Opus frames unreliably, the server relays them to players in cell range who have voip on and want that speaker's channel (everyone, party or strangers), with a per speaker rate limit. Voice:bVoip in STServer.ini turns it on for a server and is sent to clients in the server settings. The game client keeps its own [Voice] keys in the same file, so saving the server's ini now keeps keys it doesn't own instead of rewriting the file from scratch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
The microphone is captured with miniaudio, gated, Opus encoded and sent to the server. Remote voices are decoded into small jitter buffers and mixed on the voip output device, full volume up to the fade start and silent at twice that distance from the camera, panned left and right. Settings live in [Voice] of Data/SkyrimTogetherReborn/config/STServer.ini: input and output device, bVoip (Connect to voip, the same key a server uses), channel, fade start, mic volume and noise gate. The input device defaults to none, so nothing is captured until a player picks one. The noise gate, falloff, panning and jitter buffer are game independent and unit tested in TPTests. The camera transform offsets were checked in Ghidra on 1.7.104 earlier (see the comment in VoiceService.cpp). New dependencies: libopus 1.5.2 (BSD-3-Clause) and miniaudio 0.11.22 (public domain or MIT-0), Windows client only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Settings gets a Voice chat section: input device (None by default), Connect to voip, output device (the game's device by default), channel and fade start. The Player List and Party Menu tabs get a Voip column: the header mic opens your microphone volume and a noise gate with a live level meter, each player's speaker opens their volume. Speakers show one wave when the player is quiet and two while their voice gets through, party members in the party colour. Per player volumes are kept in the UI store as playerUi_voiceVolumes, by username, so they carry across servers and sessions. The F2 menu itself is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Opus is BSD-3-Clause, which asks binary redistributions to include its copyright notice and licence. THIRD_PARTY_NOTICES.txt is copied next to SkyrimTogether.exe on install, so it ends up in the release zip. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Owner
Author
|
default non selected device makes my laptop on 1.7.104 not send voice, it received noise gated voip from my 1.6.1170 pc. |
Upstream dev renamed TESCamera::cameraNode (NiNode*) to cameraRoot (NiPointer<NiNode>). Both are a single pointer at 0x20, so read it by offset and the voice listener compiles against either header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Owner
Author
Default received voice playback to 250 percent and save the setting in STServer.ini. Multiply per-player and distance gains without changing microphone capture, and retain the final output clamp. Validation: client release build and production UI build passed; TPTests passed 134 assertions in 12 cases. In-game listening and persistence checks remain.
The master volume slider still goes up to 500%. Invalid saved values now fall back to 100% too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxNiMZ7kPLL1PGMuxYo
On the world map the camera sits high in the sky, so every nearby player fell outside the voice range. When the camera is more than 1000 units from the character (map, free camera, some cutscenes), use the character's position and heading as the listener instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
The map camera check now uses the player's fade start (2500 by default) instead of a fixed 1000 units, so one setting controls both. Vanilla third person tops out around 750 units, which leaves room for camera mods. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
Past the fade start voices now lose 6 dB each time the distance doubles (inverse square law) instead of dropping in a straight line, and ease out to silence between 2x and 4x the fade start instead of cutting off at 2x. The default fade start goes from 2500 to 2000: full volume to about 29 m, -6 dB at 57 m, about -16 dB at 86 m, silent at 114 m. Saved ini values are kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
The settings hint names where voices start to fade and where they go silent, without describing the curve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018fvQxRbmmR1Uv7KRvfWVgW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Why?
Other voip solutions were either a) not allowed in this fork, b) not preferred after mumble investigation. So: c) Opus integrated
Built-in proximity voice chat
Players can talk to each other in game over the existing game connection. There's no Mumble, no separate program and no extra port, so it works the same on VPS-hosted servers and on servers players host themselves.
How it works
kUnreliableNoNagle), about 3 KB/s per player while talking.Settings
All voice settings are in
[Voice]ofData/SkyrimTogetherReborn/config/STServer.ini.bVoipis one switch: for a server it allows voip, for a player it is the Connect to voip checkbox. Voice runs only when both the server's and the player'sbVoipare on.bVoipfalsesInputDevicedefaultfollows WindowssOutputDevicesVoipChanneleveryoneeveryone,partyorstrangersfVoipFadeStart2500fMicVolume1.0fNoiseGate0.10playerUi_voiceVolumes, keyed by username, so they carry across servers and sessions.SaveSettingsToIninow starts from the file on disk, so the server keeps keys it doesn't own (the player's[Voice]keys) instead of rewriting the file from scratch.UI
Protocol
VoiceDataRequest,VoiceStateRequestandNotifyVoiceData. Frame data is capped at 512 bytes when reading.ServerSettings.VoipEnabledis new.Dependencies and licences
THIRD_PARTY_NOTICES.txthas its notice and is copied next toSkyrimTogether.exeon install, so it ends up in the release zip.Reverse engineering (Ghidra)
NiAVObjectworld transform: rotate at0x7C, translate at0xA0(NiAVObject::UpdateWorldData).TESCamera::cameraNodeat+0x20(camera position getter, ID 50785).PlayerCamera::Get,PlayerCharacter::Getand actor positions. If the camera node can't be read, the player's position and heading are used instead.CEF and the Skyrim Together UI
app-dropdownand the existing slider styling.@angular/cdkwas already a dependency).cdk/overlay-prebuilt.cssis now imported instyles.scss.rem/em, so the new parts follow the Settings font size (it sets the root font size). Checked at XS and XL in the browser mock.en.jsonunderCOMPONENT.SETTINGS.VOICEandCOMPONENT.VOIP. Other languages fall back to English. Device names come from Windows and aren't translated.Tested
TPTests, built and run with g++ on Linux)VoiceAudio.cpp(miniaudio and Opus) compiles with g++ against the real headersng build --configuration=production)bVoip=false: no audio is captured or relayedSTServer.iniby hand while the game runs (it is re-read when Settings opens)Known limitations and follow-ups
bVoip, so speakers can look on when the server has voip off.STServer.inion shutdown with the values it loaded at startup. AbVoipchange made in game while that server runs can be lost.