Skip to content

Commit e80615d

Browse files
committed
Implement ffmpeg log flushing
1 parent 956a795 commit e80615d

1 file changed

Lines changed: 53 additions & 11 deletions

File tree

cmd/main.go

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,35 @@ func (s *StreamState) stopStream(logger *zap.Logger) {
8282

8383
logger.Info("Stopping existing stream...")
8484

85-
// Stop FFmpeg process
86-
if s.ffmpegCmd != nil && s.ffmpegCmd.Process != nil {
87-
logger.Debug("Terminating FFmpeg process")
88-
if err := s.ffmpegCmd.Process.Kill(); err != nil {
89-
logger.Warn("Failed to kill FFmpeg process", zap.Error(err))
90-
}
91-
}
92-
9385
// Cancel Chrome context
9486
if s.chromeCancel != nil {
9587
logger.Debug("Cancelling Chrome context")
9688
s.chromeCancel()
9789
}
9890

91+
// Ask FFmpeg to terminate gracefully
92+
if s.ffmpegCmd != nil && s.ffmpegCmd.Process != nil {
93+
logger.Debug("Sending SIGTERM to FFmpeg process")
94+
_ = s.ffmpegCmd.Process.Signal(syscall.SIGTERM)
95+
96+
done := make(chan struct{})
97+
go func(cmd *exec.Cmd) {
98+
// Wait will reap the process and free OS resources
99+
_, _ = cmd.Process.Wait()
100+
close(done)
101+
}(s.ffmpegCmd)
102+
103+
select {
104+
case <-done:
105+
logger.Debug("FFmpeg exited gracefully")
106+
case <-time.After(5 * time.Second):
107+
logger.Warn("FFmpeg did not exit in time, killing")
108+
_ = s.ffmpegCmd.Process.Kill()
109+
// Ensure we still reap it
110+
go func(cmd *exec.Cmd) { _, _ = cmd.Process.Wait() }(s.ffmpegCmd)
111+
}
112+
}
113+
99114
// Cancel main stream context
100115
if s.cancelFunc != nil {
101116
logger.Debug("Cancelling stream context")
@@ -202,17 +217,20 @@ func main() {
202217
}()
203218

204219
// Setup stream status checker (will start monitoring after stream begins)
205-
setupStreamStatusChecker(ctx, config)
220+
cronScheduler := setupStreamStatusChecker(ctx, config)
206221

207222
// Handle graceful shutdown
208223
c := make(chan os.Signal, 1)
209224
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
210225
go func() {
211226
<-c
212227
logger.Info("Received shutdown signal, stopping...")
213-
228+
signal.Stop(c)
214229
// Stop current stream if running
215230
StopCurrentStream(ctx)
231+
if cronScheduler != nil {
232+
cronScheduler.Stop()
233+
}
216234

217235
// Shutdown HTTP server
218236
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
@@ -497,6 +515,28 @@ func startFFmpegStream(ctx context.Context, config *Config, display string, stre
497515
return fmt.Errorf("failed to start ffmpeg: %v", err)
498516
}
499517

518+
// Start a goroutine to periodically flush the zapWriter while the command is running
519+
go func() {
520+
ticker := time.NewTicker(2 * time.Second)
521+
defer ticker.Stop()
522+
523+
for {
524+
select {
525+
case <-ticker.C:
526+
// Check if the process is still running
527+
if cmd.Process != nil && cmd.ProcessState == nil {
528+
// Sync forces any buffered output to be written
529+
zapWriter.Sync()
530+
} else {
531+
// Process is done or never started
532+
return
533+
}
534+
case <-ctx.Done():
535+
return
536+
}
537+
}
538+
}()
539+
500540
// Register this stream as running
501541
globalStreamState.setStreamRunning(streamCancel, chromeCancel, cmd)
502542

@@ -526,7 +566,7 @@ func startFFmpegStream(ctx context.Context, config *Config, display string, stre
526566
// If the proper enviromental variables are set, setup a cron job to check the status of the stream
527567
// If the stream is not live, then restart the stream
528568
// This is used because various platforms have maximum stream durations and after that we need to restart
529-
func setupStreamStatusChecker(ctx context.Context, config *Config) {
569+
func setupStreamStatusChecker(ctx context.Context, config *Config) *cron.Cron {
530570
logger := utils.GetLoggerFromContext(ctx)
531571

532572
logger.Debug("Setting up stream status checker")
@@ -568,7 +608,9 @@ func setupStreamStatusChecker(ctx context.Context, config *Config) {
568608
})
569609
c.Start()
570610
logger.Info("Stream status checker started", zap.String("cronString", cronString))
611+
return c
571612
} else {
572613
logger.Debug("Stream status checker not configured, skipping setup")
573614
}
615+
return nil
574616
}

0 commit comments

Comments
 (0)