diff --git a/ffmpeg/parse/parser.go b/ffmpeg/parse/parser.go index ee1faa95..31965115 100644 --- a/ffmpeg/parse/parser.go +++ b/ffmpeg/parse/parser.go @@ -58,6 +58,7 @@ type Config struct { type parser struct { re struct { + logline *regexp.Regexp frame *regexp.Regexp quantizer *regexp.Regexp size *regexp.Regexp @@ -147,6 +148,7 @@ func New(config Config) Parser { p.averager.window = 30 * time.Second p.averager.granularity = time.Second + p.re.logline = regexp.MustCompile(`^(?:\[.*? @ .*?\] )?(?:\[[a-z]+\] )?(.*)`) p.re.frame = regexp.MustCompile(`frame=\s*([0-9]+)`) p.re.quantizer = regexp.MustCompile(`q=\s*([0-9\.]+)`) p.re.size = regexp.MustCompile(`size=\s*([0-9]+)kB`) @@ -201,13 +203,16 @@ func New(config Config) Parser { } func (p *parser) Parse(line []byte) uint64 { - isDefaultProgress := bytes.HasPrefix(line, []byte("frame=")) - isFFmpegInputs := bytes.Contains(line, []byte("ffmpeg.inputs:")) - isFFmpegOutputs := bytes.Contains(line, []byte("ffmpeg.outputs:")) - isFFmpegMapping := bytes.Contains(line, []byte("ffmpeg.mapping:")) - isFFmpegProgress := bytes.Contains(line, []byte("ffmpeg.progress:")) - isHLSStreamMap := bytes.Contains(line, []byte("hls.streammap:")) - isAVstreamProgress := bytes.Contains(line, []byte("avstream.progress:")) + matches := p.re.logline.FindSubmatch(line) + msg := matches[1] + + isDefaultProgress := bytes.HasPrefix(msg, []byte("frame=")) + isFFmpegInputs := bytes.HasPrefix(msg, []byte("ffmpeg.inputs:")) + isFFmpegOutputs := bytes.HasPrefix(msg, []byte("ffmpeg.outputs:")) + isFFmpegMapping := bytes.HasPrefix(msg, []byte("ffmpeg.mapping:")) + isFFmpegProgress := bytes.HasPrefix(msg, []byte("ffmpeg.progress:")) + isHLSStreamMap := bytes.HasPrefix(msg, []byte("hls.streammap:")) + isAVstreamProgress := bytes.HasPrefix(msg, []byte("avstream.progress:")) p.lock.log.Lock() if p.logStart.IsZero() { @@ -238,8 +243,7 @@ func (p *parser) Parse(line []byte) uint64 { p.lock.progress.Lock() defer p.lock.progress.Unlock() - _, line, _ = bytes.Cut(line, []byte("ffmpeg.inputs:")) - if err := p.parseFFmpegIO("input", line); err != nil { + if err := p.parseFFmpegIO("input", bytes.TrimPrefix(msg, []byte("ffmpeg.inputs:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -253,8 +257,7 @@ func (p *parser) Parse(line []byte) uint64 { p.lock.progress.Lock() defer p.lock.progress.Unlock() - _, line, _ = bytes.Cut(line, []byte("hls.streammap:")) - if err := p.parseHLSStreamMap(line); err != nil { + if err := p.parseHLSStreamMap(bytes.TrimPrefix(msg, []byte("hls.streammap:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -268,8 +271,7 @@ func (p *parser) Parse(line []byte) uint64 { p.lock.progress.Lock() defer p.lock.progress.Unlock() - _, line, _ = bytes.Cut(line, []byte("ffmpeg.outputs:")) - if err := p.parseFFmpegIO("output", line); err != nil { + if err := p.parseFFmpegIO("output", bytes.TrimPrefix(msg, []byte("ffmpeg.outputs:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -302,8 +304,7 @@ func (p *parser) Parse(line []byte) uint64 { p.lock.progress.Lock() defer p.lock.progress.Unlock() - _, line, _ = bytes.Cut(line, []byte("ffmpeg.mapping:")) - if err := p.parseFFmpegMapping(line); err != nil { + if err := p.parseFFmpegMapping(bytes.TrimPrefix(msg, []byte("ffmpeg.mapping:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -380,8 +381,7 @@ func (p *parser) Parse(line []byte) uint64 { // Update the progress if isAVstreamProgress { - _, line, _ = bytes.Cut(line, []byte("avstream.progress:")) - if err := p.parseAVstreamProgress(line); err != nil { + if err := p.parseAVstreamProgress(bytes.TrimPrefix(msg, []byte("avstream.progress:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -392,7 +392,7 @@ func (p *parser) Parse(line []byte) uint64 { } if isDefaultProgress { - if err := p.parseDefaultProgress(line); err != nil { + if err := p.parseDefaultProgress(msg); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, @@ -400,8 +400,7 @@ func (p *parser) Parse(line []byte) uint64 { return 0 } } else if isFFmpegProgress { - _, line, _ = bytes.Cut(line, []byte("ffmpeg.progress:")) - if err := p.parseFFmpegProgress(line); err != nil { + if err := p.parseFFmpegProgress(bytes.TrimPrefix(msg, []byte("ffmpeg.progress:"))); err != nil { p.logger.WithFields(log.Fields{ "line": line, "error": err, diff --git a/ffmpeg/prelude/prelude.go b/ffmpeg/prelude/prelude.go index 96d242a5..0250e416 100644 --- a/ffmpeg/prelude/prelude.go +++ b/ffmpeg/prelude/prelude.go @@ -34,10 +34,11 @@ type IO struct { // Parse parses the inputs and outputs from the default FFmpeg output. It returns a list of // detected inputs and outputs as well as the number of outputs according to the stream mapping. func Parse(lines []string) (inputs, outputs []IO, noutputs int) { + reLogline := regexp.MustCompile(`^(?:\[.*? @ .*?\] )?(?:\[[a-z]+\] )?(.*)`) // Input #0, lavfi, from 'testsrc=size=1280x720:rate=25': // Input #1, lavfi, from 'anullsrc=r=44100:cl=stereo': // Output #0, hls, to './data/testsrc.m3u8': - reFormat := regexp.MustCompile(`^(?:\[[a-z]+\] )?(Input|Output) #([0-9]+), (.*?), (from|to) '([^']+)`) + reFormat := regexp.MustCompile(`^(Input|Output) #([0-9]+), (.*?), (from|to) '([^']+)`) // Duration: 00:01:02.28, start: 0.000000, bitrate: 5895 kb/s // Duration: N/A, start: 0.000000, bitrate: 5895 kb/s @@ -56,8 +57,8 @@ func Parse(lines []string) (inputs, outputs []IO, noutputs int) { reStreamAudio := regexp.MustCompile(`, ([0-9]+) Hz, ([^,]+)`) reStreamBitrate := regexp.MustCompile(`, ([0-9]+) kb/s`) - reStreamMapping := regexp.MustCompile(`^(?:\[[a-z]+\] )?Stream mapping:`) - reStreamMap := regexp.MustCompile(`^(?:\[[a-z]+\])?[\s]+Stream #[0-9]+:[0-9]+`) + reStreamMapping := regexp.MustCompile(`^Stream mapping:`) + reStreamMap := regexp.MustCompile(`^[\s]+Stream #[0-9]+:[0-9]+`) iotype := "" format := "" @@ -67,6 +68,9 @@ func Parse(lines []string) (inputs, outputs []IO, noutputs int) { streamMapping := false for _, line := range lines { + matches := reLogline.FindStringSubmatch(line) + line := matches[1] + if reStreamMapping.MatchString(line) { streamMapping = true continue