Repository navigation
Releases: dmitry-ra/stv-watch
Release list
stv-watch 0.7.1
stv-watch joins a SourceTV relay of Half-Life 2: Deathmatch or Team Fortress 2 as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.7.0:
- On PyPI.
uv tool install stv-watch(orpipx install stv-watch) installs thestv-watchcommand; a clone withuv runstays the way to run from source, with the tests, the tools and the sample recording. - README, AGENTS.md and the skill show the installed command; the demo is recorded with 0.7.1.
The program is the same as 0.7.0. Checks: the wheel installed with uv tool install on a clean Ubuntu 24.04 VM, its replay of tests/data/sample.tvd gives the same events as 0.7.0; 469 tests.
stv-watch 0.7.0
stv-watch joins a SourceTV relay of Half-Life 2: Deathmatch or Team Fortress 2 as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.6.1:
- Team Fortress 2.
--game tf2watches a TF2 relay: chat channels includingcoachandlocation, the kill feed with the assister, headshots and backstabs, a Dead Ringer's faked death markedfeigned, teams RED and BLU. Voice is the samesteamcodec and is recognized as before. - Game profiles. What differs between the games (SendTable CRC by build, user message ids, chat formats, teams, the userinfo sent at CONNECTED, kill details, who hears whom) lives in
stvwatch/games/.--gamedefaults tohl2dm. - A relay of another game is refused before connecting, by the A2S folder (
hl2mp/tf): exit code 2 naming the option to use, also under--keep-trying. A relay of a game stv-watch does not know is refused with exit code 3. - The game is recorded in
capture.tvdandmeta.json;--replayand--followtake it from the recording. A recording from before 0.7.0 has none and reads ashl2dm(or--game). - userinfo compressed with Snappy (
SNAP), as TF2 relays send a full table; before, every player stayed#userid. - A session that leaves FULL within 10 s is not productive: the reconnect delay grows (4, 8, 16, 30 s) instead of staying at 2 s.
tools/read_crc.pyandtools/read_usermessages.pytake--game.
Checks: 469 tests; 53 HL2DM recordings replayed against 0.6.1 line for line, transcripts and WAV by sha256 with no difference; 14 sessions on 11 public TF2 relays (12.3 hours) replayed with recognition with no difference, every live session reached FULL and left cleanly.
stv-watch 0.6.1
stv-watch joins a Half-Life 2: Deathmatch SourceTV relay as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.6.0:
- Voice from a bot's slot is named, not checked. When SourceTV talks (as a server plugin can make it), its voice is signed with the server's own SteamID, and 0.6.0 reported it as a forgery: empty
nick,verified: false,slot_steamid64: 0. Now a slot the server marks as a fake client (guidBOTinuserinfo) gives itstalkandvoicelinesbot: trueand the slot'snick; thevoiceline has noverifiedand noslot_steamid64. The screen shows the name and a dim[bot]. A player without an account yet (friendsID 0) is not a bot and is still checked. - Someone signing as the bot is still caught. If a message of such an utterance comes from a player's slot, the
voiceline has nobotand readsverified: falsewith that player'sslot_steamid64. - Non-player SteamIDs read in Steam3, as the server's
statusprints them ([A:1:1234567:4321]), instead of a nonsenseSTEAM_0:x:n; players keepSTEAM_0:x:n. - Schema:
botis allowed ontalkandvoice(alwaystrue);verifiedis required onvoiceonly withoutbot, and forbidden with it.
stv-watch 0.6.0
stv-watch joins a Half-Life 2: Deathmatch SourceTV relay as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.5.0:
- An ordered event stream.
events.jsonl,--jsonandfeed.logare written in non-decreasingt_utc, andt_utcof every line is the moment of its event on the recording clock. A replay gives the same lines at any--speed, and the same as live. The stream holds lines back only from the moment an utterance closes until its text is ready; without--asrnothing is held. - Voice as
talkandvoice.talkcomes at the first packet of an utterance;voicewhen it closed and its text is ready, withstart_utcandend_utcof the speech (t_end_utcis gone). The two shareutt. This changes the format: a reader that tookt_utcof a voice line as the start of speech should readstart_utc. - Rotation is a cut of the stream.
rotateis the last line of the oldevents.jsonland nothing follows it; concatenated sessions are the whole run. An utterance across a cut has itstalkline in the old session and itsvoiceline, WAV and transcript row in the session where it closes. WAV files no longer move between directories. - Relays with
tv_password. The password comes from--password-file,STV_WATCH_PASSWORDor a per-relay store$XDG_CONFIG_HOME/stv-watch/passwords, and is sent only to a relay that announces one. It never reaches argv, session files, the screen or logs. --keep-tryingfor a window that should stay up: refusals and network client deaths wait (300 s doubling to 30 min after a refusal, 10 s to 300 s after a client death) instead of exiting, re-reading the password before every attempt; each wait is awaitline.- Exit codes by class: 0 done as asked, 1 bug, 2 usage or configuration, 3 the relay does not accept us, 4 the network client died, 5 the session cannot be written. Every
events.jsonlends withdone(orrotate), whose fields say how the run ended;meta.jsonis written atomically and beforedone. Newquitlabels:client left: time limit,client died (rc N),time limit.
stv-watch 0.5.0
stv-watch joins a Half-Life 2: Deathmatch SourceTV relay as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.4.0:
- Session rotation.
--rotate "0 6 * * *"starts a new session directory on a cron schedule (five fields, in the--tzzone, UTC without it), by recording time, in every source mode. The relay connection stays up. The new directory and all its files are created and opened first; then the oldevents.jsonlends with arotateline that names the newevents.jsonland directory; then the old files are closed. A phrase still being spoken or recognized at the boundary goes whole into the new session. Live, the network client rotatescapture.tvditself, and the old capture ends with a record pointing to the new one. Off by default. A schedule with other than five fields, or one that never fires, is refused at start. - An attached screen keeps its own time zone.
--attach --tz ZONEshows times in that zone; without--tzthe screen uses the engine's. The engine now sends times as UTC data rather than drawn text. The serve protocol is 3; a screen and an engine of different protocols refuse each other. - onnxruntime telemetry is off. onnxruntime 1.29 and later on Linux uploads usage events to Microsoft and keeps a device id in
~/.cache/Microsoft. stv-watch setsORT_DISABLE_TELEMETRY=1before onnxruntime is loaded, unless you set the variable yourself. - The kills line is
kills N N/min. Thetop NICK Nsuffix is gone: it was keyed by nick and never reset, so it said little. - Docs: the README was checked step by step on a clean Ubuntu 24.04 VM and fixed where it fell short. It now covers rotation, the SourceTV port,
--followand the session files. A skill for coding agents is inskills/stv-watch/.
stv-watch 0.4.0
First tagged release.
stv-watch joins a Half-Life 2: Deathmatch SourceTV relay as a spectator and shows voice (with a transcript), chat and game events, live or from a recording.
Since 0.3.0:
- Attached screens are marked. A screen run with
--attachlabels the rule over its blockattachedin its own colour, and the q hint says what q does:q quit - stops the engineon the engine's own screen,q close screen - engine keeps runningon an attached one. The serve protocol is now 2; a screen and an engine of different protocols refuse each other with both versions named. - The version at a release tag is bare. Run from a checkout at tag
v0.4.0with no changes, stv-watch reports0.4.0; elsewhere the commit is still added (+g...,.dirty). - Nemotron weights come from the k2-fsa
asr-modelsrelease, as the Silero VAD weights do; the archive and every file in it are checked by sha256. A killed download no longer leaves partial files in the model cache. - Python 3.12 to 3.14, each tested in CI; the local test server no longer needs
os.pidfd_open, which some Python builds lack. - Docs: protocol background, the sources of the protocol notes, prior art.
