From 0ab2c6e316ffc13992a66af8e14d5cd3a87a734f Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Thu, 26 Mar 2026 13:15:35 +0100 Subject: [PATCH] feat(03-02): wire RunSynthesis and add encoding feedback messages - Add encode import to cmd/netsynth/main.go - Remove TODO(phase-3) stub and _ = collectedSnapshots - Print protocol summary BEFORE encoding (D-08) - Add 'Encoding N windows to path...' status message (D-07) - Add 'Saved path (Xs, N KB, encoded in Xs)' confirmation (D-09) - Update Long description: remove '(in future phases)' qualifier - Audio duration uses float64 to avoid integer truncation (Pitfall 4) --- cmd/netsynth/main.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/cmd/netsynth/main.go b/cmd/netsynth/main.go index f727191..6c0ed14 100644 --- a/cmd/netsynth/main.go +++ b/cmd/netsynth/main.go @@ -15,6 +15,7 @@ import ( "github.com/netsynth/netsynth/aggregate" "github.com/netsynth/netsynth/capture" "github.com/netsynth/netsynth/classify" + "github.com/netsynth/netsynth/encode" ) var ( @@ -28,7 +29,7 @@ func main() { rootCmd := &cobra.Command{ Use: "netsynth", Short: "Sonify live network traffic into ambient audio", - Long: "NetSynth captures network traffic, classifies it by protocol, and (in future phases) synthesizes an ambient MP3 soundscape.", + Long: "NetSynth captures network traffic, classifies it by protocol, and synthesizes an ambient MP3 soundscape.", RunE: run, } @@ -96,16 +97,29 @@ func run(cmd *cobra.Command, args []string) error { aggregate.AccumulateTotals(totals, snap) } - // TODO(phase-3): Pass collectedSnapshots to encode.RunSynthesis(collectedSnapshots, outputPath) - _ = collectedSnapshots - - // Print exit summary (CLAS-03) + // D-08: Print protocol summary BEFORE encoding — user sees stats immediately dropped := atomic.LoadInt64(droppedPtr) if dropped > 0 { fmt.Fprintf(os.Stderr, "\nWarning: %d packets dropped (channel buffer full)\n", dropped) } aggregate.PrintSummary(os.Stderr, totals) + // D-07: Encoding status line + fmt.Fprintf(os.Stderr, "Encoding %d windows to %s...\n", len(collectedSnapshots), outputPath) + encodeStart := time.Now() + if err := encode.RunSynthesis(collectedSnapshots, outputPath); err != nil { + return fmt.Errorf("synthesis failed: %w", err) + } + encodeElapsed := time.Since(encodeStart) + + // D-09: Saved confirmation with path, audio duration, file size, encoding time + audioDuration := float64(len(collectedSnapshots)) * float64(aggregate.DefaultWindowMs) / 1000.0 + info, statErr := os.Stat(outputPath) + if statErr != nil { + return fmt.Errorf("stat output file: %w", statErr) + } + fmt.Fprintf(os.Stderr, "Saved %s (%.1fs, %d KB, encoded in %.1fs)\n", + outputPath, audioDuration, info.Size()/1024, encodeElapsed.Seconds()) return nil }