fix(v2): log redacted ffmpeg/ffprobe stderr on stream failure
The stream worker discarded ffmpeg stderr, so reconnect loops were opaque. Capture stderr and log it with the RTSP URL/credentials redacted, so the real cause (auth, timeout, option, URL parse) is diagnosable without leaking the source address. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,18 +2,32 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var rtspURLPattern = regexp.MustCompile(`rtsp://[^\s'"]+`)
|
||||
|
||||
// redact removes the resolved source URL (which may carry credentials) from any
|
||||
// FFmpeg/FFprobe diagnostic text before it is logged.
|
||||
func redact(text, sourceURL string) string {
|
||||
if sourceURL != "" {
|
||||
text = strings.ReplaceAll(text, sourceURL, "<source>")
|
||||
}
|
||||
return rtspURLPattern.ReplaceAllString(text, "rtsp://<redacted>")
|
||||
}
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
@@ -195,8 +209,12 @@ func probe(ctx context.Context, config Config) (Metadata, error) {
|
||||
args := []string{"-v", "error", "-select_streams", "v:0", "-show_entries", "stream=width,height,r_frame_rate", "-of", "json"}
|
||||
args = appendInputOptions(args, config)
|
||||
args = append(args, "-i", config.SourceURL)
|
||||
output, err := exec.CommandContext(ctx, config.FFprobePath, args...).Output()
|
||||
command := exec.CommandContext(ctx, config.FFprobePath, args...)
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
output, err := command.Output()
|
||||
if err != nil {
|
||||
log.Printf("ffprobe 探测失败:%s(%v)", strings.TrimSpace(redact(stderr.String(), config.SourceURL)), err)
|
||||
return Metadata{}, errors.New("unable to probe video metadata")
|
||||
}
|
||||
var parsed struct {
|
||||
@@ -230,7 +248,8 @@ func decode(ctx context.Context, config Config, metadata Metadata, publish func(
|
||||
args := append([]string{"-hide_banner", "-loglevel", "error"}, appendInputOptions(nil, config)...)
|
||||
args = append(args, "-i", config.SourceURL, "-an", "-sn", "-dn", "-f", "rawvideo", "-pix_fmt", "bgr24", "-")
|
||||
command := exec.CommandContext(ctx, config.FFmpegPath, args...)
|
||||
command.Stderr = io.Discard
|
||||
var stderr bytes.Buffer
|
||||
command.Stderr = &stderr
|
||||
stdout, err := command.StdoutPipe()
|
||||
if err != nil {
|
||||
return errors.New("unable to read video frames")
|
||||
@@ -247,6 +266,7 @@ func decode(ctx context.Context, config Config, metadata Metadata, publish func(
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
log.Printf("ffmpeg 解码停止:%s(%v)", strings.TrimSpace(redact(stderr.String(), config.SourceURL)), err)
|
||||
return errors.New("video decoder stopped")
|
||||
}
|
||||
publish(frame)
|
||||
|
||||
Reference in New Issue
Block a user