fix: millisecond segment in the recording filename so two instances can't clobber a take
The dev multi-instance use case (one instance screen-capturing the other for
marketing/training videos) exposed a real bug. BuildStartPath in
MainViewModel.Recording.cs builds the start name with no dedup:
var name = RecordingFile.BuildStartName(DateTime.Now) + ".mp4";
var path = Path.Combine(folder, name);
Only FinalizeRecordingAsync calls UniquePath. So two instances that start
recording in the same minute computed the identical path
(ty-20260927-1454-0000.mp4) and both ffmpeg processes wrote one file -- a
corrupt take, not an error message.
Creator's fix (2026-09-27): add a millisecond count to the filename timestamp.
New format is ty-<yyyyMMdd>-<HHmm>-<fff>-<hh2mm2>.mp4. Both the start name and
the final name derive from _recordStartTime, so the ffff segment survives the
rename-on-stop and the final name cannot collide with another same-minute take
either. No UniquePath call needed, which keeps the start path a pure function of
the timestamp and the existing collision suffix behaviour intact.
Tests: 2 new (the same-minute guard and the rename-survival guard), 5 existing
assertions updated for the format. RecordingSaveDialogTests' stem fixtures
updated to match. 369/369 pass, 0 warnings.
Note: the first test run reported 367/367 because only ytLive.csproj had been
built -- the stale test DLL never picked up the new tests. The real count is 369.
This commit is contained in:
@@ -717,10 +717,14 @@ lights when a session is actually running.
|
||||
gold/red/green). The account **status dot is gone** — the avatar/Sign In pair carries connectedness.
|
||||
`ShowPrimaryStartButton` remains the always-idle face. `StopStream` clears both pills (see "Stop ends
|
||||
everything; failures roll back" below).
|
||||
- **Filenames** (pure `Services/RecordingFile`): auto-name `ty-<yyyyMMdd>-<HHmm start>-0000.mp4` at start;
|
||||
**rename-on-stop** to `ty-…-<hh2mm2 actual length>.mp4` (`FinalizeRecordingAsync` after the pump stops &
|
||||
the file closes), numeric `-2`/`-3` suffix on collision (`UniquePath`). Length comes from `_liveElapsed`,
|
||||
which the session timer walks while `IsLive || IsRecording`.
|
||||
- **Filenames** (pure `Services/RecordingFile`): auto-name `ty-<yyyyMMdd>-<HHmm start>-<fff>-0000.mp4` at
|
||||
start; **rename-on-stop** to `ty-…-<hh2mm2 actual length>.mp4` (`FinalizeRecordingAsync` after the pump
|
||||
stops & the file closes), numeric `-2`/`-3` suffix on collision (`UniquePath`). Length comes from
|
||||
`_liveElapsed`, which the session timer walks while `IsLive || IsRecording`. The **`<fff>` millisecond
|
||||
segment is load-bearing, not decoration** (2026-09-27): both names derive from `_recordStartTime`, so it
|
||||
survives the rename, and without it two instances started in the same minute compute the *same* start
|
||||
path and both ffmpeg processes write one file — which is exactly the dev multi-instance case
|
||||
(`Helpers/InstanceProfile`, one instance recording the other).
|
||||
- **Save dialog: Cancel DISCARDS (creator ruling 2026-09-26).** The `RenameRecordingDialog` result is a
|
||||
two-outcome decision, and it lives in the extracted `MainViewModel.CompleteRecordingSave(startPath, dir,
|
||||
autoStem, chosenStem, creatorSaved)` (internal, so `ytLive.Tests` can drive it against real files without
|
||||
|
||||
Reference in New Issue
Block a user