sweep capture and mavpoll for duplication and magic values (V-581)

capture: one Session.discard for the reaper and Abort, which both closed
the spool and deleted it by hand. One abandon closure for the two failed
Start paths. bytesPerSample and bytesPerSecond replace three copies of
the byte-rate arithmetic.

mavpoll: unchanged and writeFact hold the read-compare and the row shape,
so the three fact writers keep only what differs between them, their log
line. The wg key and source are named constants. Named coreDialWait,
zenTimeoutFactor, maxBodyBytes and factConfidence. run lost the zenmoney
setup to newZenClient and the ticker to loop.

Comments only where they were stale: the package doc counted two sources
and there are four.
This commit is contained in:
2026-08-06 01:54:38 +04:00
parent 59b98d5c4d
commit db8cbdc20a
2 changed files with 144 additions and 84 deletions
+38 -26
View File
@@ -161,6 +161,18 @@ func (s *Session) finish() error {
return s.spool.Sync()
}
// discard closes the spool and deletes it, leaving nothing behind. Used by the
// reaper and by Abort, which throw a recording away rather than harvest it.
func (s *Session) discard() {
s.mu.Lock()
_ = s.finish()
path := s.path
s.mu.Unlock()
if path != "" {
_ = os.Remove(path)
}
}
// Duration is how much audio has been collected, from the bytes rather than the
// wall clock: a stream that dropped frames should report the audio that exists,
// not the time that passed.
@@ -174,9 +186,16 @@ func (s *Session) duration() time.Duration {
return pcmDuration(s.format, s.n)
}
// bytesPerSample is one sample across all channels. Cutting a buffer anywhere
// that is not a multiple of it shifts every following sample by a byte.
func bytesPerSample(f audio.Format) int64 { return int64(f.SampleBits / 8 * f.Channels) }
// bytesPerSecond is the format's byte rate, 32000 for the canonical 16 kHz mono.
func bytesPerSecond(f audio.Format) int64 { return int64(f.SampleRate) * bytesPerSample(f) }
// pcmDuration is how long n bytes of PCM lasts in the given format.
func pcmDuration(f audio.Format, n int64) time.Duration {
per := int64(f.SampleRate) * int64(f.Channels) * int64(f.SampleBits) / 8
per := bytesPerSecond(f)
if per <= 0 {
return 0
}
@@ -279,19 +298,21 @@ func (r *Recorder) Start(label string) (*Session, error) {
f.Close()
return nil, err
}
// A session that never opened leaves no spool file behind.
abandon := func(err error) (*Session, error) {
f.Close()
_ = os.Remove(f.Name())
return nil, err
}
// The header is written first and rewritten at Stop with the real length,
// so the spool file is a playable WAV rather than headerless PCM that has
// to be copied to gain 44 bytes.
if _, err := f.Write(hdr); err != nil {
f.Close()
_ = os.Remove(f.Name())
return nil, fmt.Errorf("capture: spool header: %w", err)
return abandon(fmt.Errorf("capture: spool header: %w", err))
}
token, err := newToken()
if err != nil {
f.Close()
_ = os.Remove(f.Name())
return nil, err
return abandon(err)
}
s := &Session{
Label: strings.TrimSpace(label),
@@ -330,15 +351,11 @@ func (r *Recorder) reapLocked() {
}
s.mu.Lock()
s.expired = true
_ = s.finish()
path := s.path
s.mu.Unlock()
if path != "" {
// The audio goes with it. A recording nobody stopped is one nobody is
// waiting for, and keeping it would mean storing a meeting on the
// strength of a dropped connection.
_ = os.Remove(path)
}
// The audio goes with it. A recording nobody stopped is one nobody is
// waiting for, and keeping it would mean storing a meeting on the strength
// of a dropped connection.
s.discard()
r.current = nil
}
@@ -536,13 +553,7 @@ func (r *Recorder) Abort(token string) bool {
return false
}
r.current = nil
s.mu.Lock()
_ = s.finish()
path := s.path
s.mu.Unlock()
if path != "" {
_ = os.Remove(path)
}
s.discard()
return true
}
@@ -576,7 +587,7 @@ func (r *Recorder) transcribeFile(ctx context.Context, path string, format audio
}
// Never cut mid-sample: a split inside an int16 shifts every following
// sample by a byte and turns the tail of the window into noise.
if bps := int64(format.SampleBits / 8 * format.Channels); bps > 0 {
if bps := bytesPerSample(format); bps > 0 {
size -= size % bps
}
if size <= 0 {
@@ -608,12 +619,13 @@ func (r *Recorder) transcribeFile(ctx context.Context, path string, format audio
// is read by him in a note next to the words around it.
const gapMarker = "[…не разобрала…]"
// windowBytes is how many PCM bytes one STT window holds.
// windowBytes is how many PCM bytes one STT window holds, rounded down to a
// whole sample.
func windowBytes(f audio.Format, window time.Duration) int64 {
bps := int64(f.SampleBits / 8 * f.Channels)
bps := bytesPerSample(f)
if bps <= 0 || f.SampleRate <= 0 || window <= 0 {
return 0
}
per := int64(window.Seconds()) * int64(f.SampleRate) * bps
per := int64(window.Seconds()) * bytesPerSecond(f)
return per - per%bps
}