diff --git a/ffmpeg-myth.scm b/ffmpeg-myth.scm index d8a79cd..62aa054 100755 --- a/ffmpeg-myth.scm +++ b/ffmpeg-myth.scm @@ -18,6 +18,7 @@ (define ffmpeg-bin "/usr/bin/ffmpeg") (define ffprobe-bin "/usr/bin/ffprobe") (define ffprobe-separator #\page) ;; +(define ffmpeg-transcoding-options "-preset slow -crf 21 -c:a ac3 -g 60 -keyint_min 30") (define recordings-directory "/var/lib/mythtv/recordings") (define working-directory "/mnt/lvraid5/ffmpeg-cut-list.d") (define mythtv-recorded-table->metadata-list '(chanid starttime endtime title subtitle description season episode recordid seriesid programid inetref previouslyshown originalairdate)) @@ -267,6 +268,49 @@ (assv-ref (recording-recorded-table rec) 'basename)) (define (recording-filesize rec) (assv-ref (recording-recorded-table rec) 'filesize)) +(define (recording-av-stream-info rec type) + (define (rvsi s r) (cond ((null? s) r) + ((eqv? (assv-ref (car s) 'codec_type) type) + (rvsi (cdr s) (cons (car s) r))) + (#t (rvsi (cdr s) r)))) + (rvsi (recording-streams-info rec) '())) +(define (recording-video-stream-ffmpeg-filt rec scale?) + (define (iter f l i acc) + (cond ((null? l) (reverse acc)) + (#t + (iter f (cdr l) (+ 1 i) (cons (f i) acc))))) + (let* ((v (car (recording-av-stream-info rec 'video))) + (a (reverse (recording-av-stream-info rec 'audio))) + (rtn (recording-retain-list rec)) + ;;(sar (assv-ref v 'sample_aspect_ratio)) + (dar (assv-ref v 'display_aspect_ratio)) + (height (assv-ref v 'height)) + (width (assv-ref v 'width)) + (idx (assv-ref v 'index)) + (aidx (map (lambda(s) (assv-ref s 'index)) a)) + (scale-flt (if scale? (let ((fmt (simple-format #f "[~~a:~a] scale=w=~a:h=~a,setdar=~a,setpts=PTS-STARTPTS [v~~a];" idx width height dar))) + (lambda (i) (simple-format #f fmt i i))) (lambda (i) ""))) + (av-ptr (lambda (i) (string-join (cons (if scale? (simple-format #f "[v~a]" i) (simple-format #f "[~a:~a]" idx i)) (map (lambda (a) (simple-format #f "[~a:~a]" i a)) aidx))))) + (out-ptr (lambda (i) (simple-format #f "[out~a]" i))) + (n (length rtn)) + (concat (simple-format #f "concat=n=~a:v=1:a=~a [out0]" n (length aidx))) + (mappings (lambda (i) (simple-format #f "-map '[out~a]'" i)))) + (string-join (append (list "'") (iter scale-flt rtn 0 '()) (iter av-ptr rtn 0 '()) (list concat) (iter out-ptr aidx 1 '()) (list "' ") (iter mappings (cons 0 aidx) 0 '()))))) +(define* (ffmpeg-split+scale+transcode-recording rec #:optional (scale? #f)) + (let* ((basename (recording-basename rec)) + (rootname+ext (string-split basename #\.)) + (rootname (car rootname+ext)) (ext (cadr rootname+ext)) + (in-file (simple-format #f "~a/~a" recordings-directory basename)) + (out-file (simple-format #f "~a/~a.~a" working-directory rootname transcoded-file-ending)) + (m-d (mythtv-recorded-table->metadata rec)) + (cut-times (myth-convert-i-frame-indices-to-times (recording-retain-list rec) (recording-i-frame-info rec))) + (seek-fn (lambda(c) (simple-format #f " -ss ~a -t ~a -i '~a'" (car c) (- (cdr c) (car c)) in-file))) + (filter (recording-video-stream-ffmpeg-filt rec scale?)) + (options ffmpeg-transcoding-options) + (cmd (simple-format #f "~a -y ~a -filter_complex ~a ~a ~a ~a" ffmpeg-bin (string-join (map seek-fn cut-times)) filter options m-d out-file))) + (shell-command-to-string cmd) + cmd)) + (define (recording-new-file-name file-name ending) (let* ((old-ending (substring file-name (- (string-length file-name) 3)))