detectads/webif/plugin/detectads/detectads.jim

1067 lines
37 KiB
Plaintext
Executable File

require queue.class
proc ::detectads::query_entry_queue_db {ts} {
set result [{queue check} $ts detectads]
return $result
}
proc ::detectads::delete_entry_queue_db {ts} {
log "Removing item [$ts get file] from the queue" 1
return [{queue delete} $ts detectads]
}
proc ::detectads::delete_orphans {} {
if {![catch {exec /mod/bin/pgrep -x chaseget }]} {return}
set fl [glob -nocomplain "/mod/tmp/*-inp.ts" "/mod/tmp/*-dec.ts"]
log "orphan file list $fl" 2
foreach file $fl {
if {![system inuse $file]} {
set bname [file rootname $file]
file delete -force $bname.hmt
file delete -force $bname.nts
file delete -force $bname.thm
file delete -force $file
log "Deleted orphan file $file"
}
}
}
# Parse command options and apply defaults
proc ::detectads::checkopts {argv} {
set ::optlist ""
set ::opt "-h"
set ::debug 0
set ::time 0
set parmerror 0
set settings [settings]
set ::autologlevel [$settings _nval_setting "autolog"]
if {![info exists ::auto::logfd]} {
set logfd ::auto::logfd
}
# List of options with default values
set optarray {
d 0
debug 0
crop 0
force 0
bmend 0
bmsil 0
delorig 0
cpulimit 0
misrdsec 30
misdetsec 5
misdetalarm 10
delsec 180
retmax 2
sildb -70
silminsec 0.2
brkminct 5
brkminsec 60
admaxsec 65
padsec 0
dirdecrypt 0
makethm 0
thmoffset 0}
# Override default from settings DB
foreach {key defvalue} [array get optarray] {
set ::opts($key) [$settings _nval_setting "detectads_$key"]
if {$::opts($key)==0} {set ::opts($key) $defvalue}
}
# Handle text setting for target path
set ::opts(tgtpath) [$settings _tval_setting "detectads_tgtpath"]
if {$::opts(tgtpath) == 0} {set ::opts(tgtpath) ""}
set ::opts(tgtchoice) [$settings _nval_setting "detectads_tgtchoice"]
# Handle text setting for oher options
set otheropts [$settings _tval_setting "detectads_otheropts"]
if {$otheropts == 0} {set otheropts ""}
# Parse argument lists
foreach argl [list $otheropts $argv] {
set ::optlist ""
log "arg list $argl" 2
for {set ix 0} {$ix < [llength $argl]} {incr ix} {
set arg [lindex $argl $ix]
#check if option in optarray list
if {[string range $arg 0 0] == "-"} {
set argx [string tolower [string range $arg 1 end]]
if {[dict exists $optarray $argx]} {
incr ix
set val [lindex $argl $ix]
set nval $val
if {$val eq "y"} {set nval 1}
if {$val eq "n"} {set nval 0}
if {![string is double -strict $nval]} {
if {[string length $nval] == 0 ||
[string range $nval 0 0] == "-"} {
# Value omitted assume true
set nval 1
set val "y"
incr ix -1
} else {
log "Option $arg value ($val) is not y, n or numeric" 0
incr ix -1
set parmerror 1
continue
}
}
lappend ::optlist $arg
lappend ::optlist $val
set ::opts($argx) $nval
continue
}
}
# check other options
switch -- $arg {
-tgt {
lappend ::optlist "-tgt"
incr ix
set tgtpath [lindex $argl $ix]
set ::opts(tgtpath) $tgtpath
lappend ::optlist ::tgtpath
if {$tgtpath eq "="} {
set ::opts(tgtchoice) 1
} else {
set ::opts(tgtchoice) 3
if {![file isdirectory $tgtpath]} {
log "Target '$tgtpath' is not a valid directory" 0
set parmerror 1
continue
}
}
}
-pq -
--help -
-h {
set ::opt $arg
}
-rs -
-aq -
-dq -
-qq -
-pr {
set ::opt $arg
incr ix
set file [lindex $argl $ix]
set ::file $file
if {[file isfile $file]} {
set ::ts [ts fetch $file]
if {$::ts == 0} {
log "Cannot process ($file) file is not valid recording" 0
set parmerror 1
continue
}
} else {
log "Cannot process ($file) file does not exist" 0
#puts "Cannot process ($file) file does not exist"
set parmerror 1
continue
}
}
-t {
incr ix
set ::time [lindex $argl $ix]
}
default {
log "Unrecognized option: $arg" 0
set parmerror 1
continue
}
}
}
}
if {$::opts(debug) || $::opts(d)} {
set ::debug 1
set ::loglevel 2
set ::auto::loglevel 2
}
if {$parmerror} {
log "Parameter errors found"
exit
}
}
proc ::detectads::chancheck {ts} {
# Check recording channel against exclusion list prior to queueing for analysis - mymsman 150404
set file [$ts get file]
set channel [$ts get channel_name]
log " DETECTADS: Checking $file ($channel) for channel exclusion" 0
set dir [file dirname $file]
if {[file exists "$dir/.autonodetectads"]} {
log " DETECTADS: No Ad-detection folder flag set $file" 0
return 0
}
if {[$ts flag "Addetection"]} {
log " DETECTADS: Ad-detection flag already set $file" 0
return 0
}
if {[$ts flag "Radio"]} {
log " DETECTADS: Radio broadcast, skipping $file" 0
return 0
}
# ignore FlatView directory
set settings [settings]
set fvdir [$settings _tval_setting "fv_dir"]
if {[file tail $dir] == $fvdir} {
log " DETECTADS: Flat view directory, skipping $file" 0
return 0
}
set opts ""
if {![file exists "$dir/.autodetectads"]} {
# open and read configuration file
set cf "/mod/etc/detectads.conf"
if {![file exists $cf]} {
file copy /mod/webif/plugin/detectads/default.conf $cf
}
if {![catch {set fp [open $cf r]}]} {
set clist [split [read $fp] "\n"]
} else {
set clist {}
}
# Match channel against exclusion list
foreach chan $clist {
if {![string length $chan]} continue
log "Checking exclusion entry: $chan" 2
if {[string match -nocase $chan $channel]} {
log "Matched exclusion entry $chan - skipping ad detection" 0
return 0
}
}
} else {
# Read options from .autodetectads file
set ado_file "$dir/.autodetectads"
set hand [open $ado_file]
set opts [gets $hand]
close $hand
}
::detectads::checkopts $opts
if {[$ts flag "ODEncrypted"]} {
set cmd [list /mod/webif/plugin/detectads/detectads -pr "$file"]
append cmd $opts
exec {*}$cmd >@$::logfd &
log " DETECTADS: Started $file for chaserun advert detection" 0
} else {
set queue_time [$settings _tval_setting "detectads_queue_time"]
set Qid [::detectads::queue $ts $queue_time]
log " DETECTADS: Queued $file for advert detection, Qid $Qid" 0
}
set ::auto::loglevel ::autologlevel
}
proc ::detectads::queue {ts {time 0} {retrynumb 0}} {
set file [$ts get file]
set start [clock seconds]
if {[string is integer -strict $time]} {
set start $time
} else {
catch {
set tstart [clock scan $time -format %H:%M]
if {$tstart<$start} {incr tstart 86400}
set start $tstart
}
}
if {$start == 0} {set start [clock seconds]}
# queue with system Q
set q [{queue insert} -hold $ts detectads]
$q set start $start
$q set args $::optlist
if {$retrynumb} {$q set retries $retrynumb}
set Qid [$q get id]
$q submit
log "Queued $file Qid $Qid" 1
return $Qid
}
proc ::detectads::run {ts} {
set file [$ts get file]
log " DETECTADS: $file $::optlist" 0
set retcode {"FAILED" "Unknown = check log"}
set warning ""
if {![acquire_lock $file]} {
log "Cannot acquire exclusive lock $file, terminating." 0
return {"DEFER" "Cannot acquire exclusive lock"}
}
set size [$ts size]
set numAdBreaks 0
set bname [file rootname [file tail $file]]
set bpath [file dirname $file]
foreach {key value} [array get ::opts] {
set $key $value
}
set tailPid 0; # unused (for killing head of pipe on timeout - useful with tail -f recording.ts | ffmpeg ... | silence...)
set silenceArgs "\
$tailPid\
$sildb\
$silminsec\
$brkminct\
$brkminsec\
$admaxsec\
$padsec"
set start [clock milliseconds]
set statustok [system startop -multiple detectads $file]
set adDetectOutput [open "|\
nice -n 19 ffmpeg -nostats -loglevel fatal -i [list $file] -vn -sn -ac 2 -f au pipe:1 2>@$::logfd |\
/mod/webif/plugin/detectads/silence $silenceArgs 2>@$::logfd" r]
set pids [pid $adDetectOutput]
log "adDetect pids $pids" 2
# cpulimit if program exists
if {$cpulimit > 0 & [file exists /mod/bin/cpulimit]} {
set curppid [lindex $pids 0]
sleep 3; # mustn't be too quick
exec /mod/bin/cpulimit -l $cpulimit -p $curppid &
log "ffmpeg pid $curppid limited to $cpulimit % of cpu"
}
set bookmarks [$ts bookmarks 1]
log "Initial bookmarks: $bookmarks" 2
set cropcmd " "
set totalEndSeconds 0
while {[gets $adDetectOutput line] != -1} {
log $line 2
set startMinutes 0
set startSeconds 0
set endMinutes 0
set endSeconds 0
# is it a cut line?
if {[regexp {^cut@= Cut[^(]*\( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalStartSeconds [expr {$startMinutes * 60 + $startSeconds}]
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
log " ad break found $startMinutes:$startSeconds-$endMinutes:$endSeconds ($totalStartSeconds - $totalEndSeconds)" 0
# ladd will not add them if they already exist
if {$bmend} {
ladd bookmarks $totalEndSeconds
} else {
# "Invert" first bookmark position to be correct for manually run nicesplice crop (from xyz321)
if {$cropcmd eq " "} {
# First bookmark
if {$totalStartSeconds == 0} {
ladd bookmarks $totalEndSeconds
} else {
ladd bookmarks 0 $totalStartSeconds $totalEndSeconds
}
} else {
ladd bookmarks $totalStartSeconds $totalEndSeconds
}
}
# Update bookmarks and build up crop cmd line as each break is detected.- mymsman 150408
$ts setbookmarks $bookmarks
lappend cropcmd -cut $($totalStartSeconds *10) $($totalEndSeconds *10)
incr numAdBreaks
if {$makethm && $numAdBreaks==1} {
# First ad break and thumbnail creation requested
# Check if it already exists
if {![file exists "$bpath/$bname.thm"]} {
# Doesn't exist create it
if {$totalStartSeconds == 0} {
set offset $($totalEndSeconds + $thmoffset)
} else {
set offset $thmoffset
}
if {$offset < 0} {set offset 0}
set thmstart [clock milliseconds]
system startop thumb $file
$ts mkthm $offset
system endop thumb
set thmend [clock milliseconds]
if {![file exists "$bpath/$bname.thm"]} {
log "Thumbnail creation failed" 0
} else {
log "Thumbnail created at offset $offset in $(($thmend-$thmstart)/1000) seconds" 0
}
}
}
}
# is it the End line?
if {[regexp {^status@= End[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
log "End: Frame $endFrame Time: $endMinutes:$endSeconds Seconds: $totalEndSeconds" 1
break
}
if {$bmsil} {
# is it a Silence? that we are bookmarking for debuging
if {[regexp {^debug@ Silence[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalStartSeconds [expr {$startMinutes * 60 + $startSeconds}]
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
ladd bookmarks $totalStartSeconds
$ts setbookmarks $bookmarks
log " Silence found $startMinutes:$startSeconds-$endMinutes:$endSeconds ($totalStartSeconds - $totalEndSeconds) Frames: $startFrame - $endFrame" 0
}
}
}
close $adDetectOutput
log "Final bookmarks: $bookmarks" 0
log "$cropcmd" 2
$ts setbookmarks $bookmarks
exec hmt +detectads "$bpath/$bname.hmt"
# Check that complete file has been retrieved & detected
set stime [$ts get start]
set etime [$ts get end]
set durn $($etime-$stime)
set misdetect $(abs($durn-$totalEndSeconds))
if {$misdetect > $misdetsec} {
# Length error in dectection
set warning "Detection Length error, Bookmarks may be upto [clock format $misdetect -format %T] out"
if {$misdetect > $misdetalarm} {
system notify "DetectAds $file $warning"
}
log "$file $warning" 0
}
# crop adbreaks out of file - mymsman 150407
if {$crop & $numAdBreaks>0 & $misdetect <= $misdetsec} {
set elapsedSeconds [elapsed $start]
set elapsedTime [clock format $(round($elapsedSeconds)) -format "%H:%M:%S"]
log "ad detection.processed in ${elapsedSeconds}s $elapsedTime - $numAdBreaks ad breaks bookmarked, crop starting" 0
# copy & paste from crop/execute.jim - mymsman 150407
set rfile $file
set dir [file dirname $rfile]
set len [$ts duration 1]
set cropstart [clock milliseconds]
switch -- $tgtchoice {
3 { # Other - check target directory exists
if {![file isdirectory $tgtpath]} {
puts "Target '$tgtpath' is not a valid directory, Check Detectads Settings page"
log "Target '$tgtpath' is not a valid directory, Check Detectads Settings page" 0
return [list "FAILED" "Target '$tgtpath' is not a valid directory, $numAdBreaks ad breaks bookmarked, $warning"]
}
}
2 { # store in My Video
set tgtpath [system mediaroot]
}
1 -
default { # Same path as input
set tgtpath [file dirname $file]
}
}
log "Target option: $tgtchoice Target path: $tgtpath" 2
set base [file rootname $rfile]
set shname [file tail $base]
# Check if thumbnail exists
if {[file exists "$bpath/$bname.thm"]} {
# Copy to crop
file copy "$bpath/$bname.thm" "$tgtpath/$shname-crop.thm"
}
set cmd [list /mod/webif/plugin/detectads/nsplice \
-in "$dir/$shname" \
-out "$tgtpath/$shname-crop" ]
append cmd " $cropcmd"
# Cant get awk working - give up for now
#set awkcmd list[awk {\{ print strftime(\"%d/%m/%Y %H:%M:%S NS([pid])-\"), \$0; fflush(); \}}]
# >@$::logfd]
log "CMD: $cmd"
#log [exec {*}$cmd | {*}$awkcmd >@$::logfd]
log [exec {*}$cmd]
set croptime [expr [expr [clock milliseconds] - $cropstart] / 1000.0]
log " crop time taken: $croptime [clock format $(round($croptime)) -format %T]" 1
if {$delorig && ![system inuse $file]} { # Delete original file no longer wanted
if {[safe_delete $file detectads]} {
log "$file deleted" 0
set cfile "$tgtpath/$shname-crop.ts"
if {![system inuse $cfile]} { # Rename crop file to original if not in use
ts renamegroup "$cfile" "$shname"
}
} else {
log "$file safe_delete failed" 0
}
} else {
set title [$ts get title]
set newtitle [concat $title "-Crop"]
exec hmt "+settitle=${newtitle}" "$tgtpath/$shname-crop.hmt"
}
set elapsedSeconds [elapsed $start]
set elapsedTime [clock format $(round($elapsedSeconds)) -format "%H:%M:%S"]
log "done...processed in ${elapsedSeconds}s $elapsedTime - $numAdBreaks ad breaks cropped out" 0
set retcode [list "OK" "$numAdBreaks ad breaks cropped out" ]
} else {
set elapsedSeconds [elapsed $start]
set elapsedTime [clock format $(round($elapsedSeconds)) -format "%H:%M:%S"]
log "done...processed in ${elapsedSeconds}s $elapsedTime - $numAdBreaks ad breaks bookmarked" 0
set retcode [list "OK" "$numAdBreaks ad breaks bookmarked, $warning"]
}
system endop $statustok
release_lock $file
set ::auto::loglevel ::autologlevel
return $retcode
}
proc ::detectads::chaserun {ts {Qid 0} {retrynumb 0}} {
# run ad detection against currently recording program using dlna helper - mymsman 150505
# creates decrypted, cropped and shrunk copy of file in video root directory.
# Original recording has ad bookmarks, set.
set file [$ts get file]
log "==DETECTADS Chase Run: $file $::optlist" 0
set retcode "OK"
set retmsg "Unknown = check log"
set qtime 0
set warning ""
set cropcmd " "
# Check for and delete any oprhaned files
::detectads::delete_orphans
if {![acquire_lock $file]} {
log "Cannot acquire exclusive lock $file, terminating." 0
return {"DEFER" "Cannot acquire exclusive lock"}
}
set statustok [system startop -multiple detectads $file]
set size [$ts size]
set numAdBreaks 0
# set each option from settings/overrides
foreach {key value} [array get ::opts] {
set $key $value
}
set tailPid 0; # unused (for killing head of pipe on timeout - useful with tail -f recording.ts | ffmpeg ... | silence...)
set silenceArgs "\
$tailPid\
$sildb\
$silminsec\
$brkminct\
$brkminsec\
$admaxsec\
$padsec"
set stime [$ts get start]
set etime [$ts get end]
set ctime [clock seconds]
if {!$dirdecrypt} {
# Check file sharing enabled
if {[system param DMS_START_ON]} {
log "Content Sharing Enabled" 2
} else {
puts "Content Sharing Disabled -cannot decrypt files"
log "Content Sharing Disabled" 0
system notify "DetectAds: Contents sharing disabled, Enable via Humax Settings menu"
return {"DEFER" "Content Sharing Disabled"}
}
}
switch -- $tgtchoice {
3 { # Other - check target directory exists
if {![file isdirectory $tgtpath]} {
puts "Target '$tgtpath' is not a valid directory, Check Detectads Settings page"
log "Target '$tgtpath' is not a valid directory, Check Detectads Settings page" 0
return [list "FAILED" "Target '$tgtpath' is not a valid directory"]
}
}
2 { # store in My Video
set tgtpath [system mediaroot]
}
1 -
default { # Same path as input
set tgtpath [file dirname $file]
}
}
log "Target option: $tgtchoice Target path: $tgtpath" 2
# if active recording and not already on queue add a protective queue entry at end+20minutes
set tempQid 0
if {$Qid == 0 & $ctime < $etime} {
set qtime $($etime + 1200)
set tempQid [::detectads::queue $ts $qtime]
log "Temp Q entry $tempQid created" 1
set defertime $qtime
}
set bname [file rootname [file tail $file]]
set iname "$bname-inp"
set tname "$bname-dec"
set cname "$bname-crop"
set bpath [file dirname $file]
#set tpath $tgtpath
set ipath "/mod/tmp"
set tpath "/mod/tmp"
set cpath $tgtpath
set bfile "$file"
set ifile "$ipath/$iname.ts"
set tfile "$tpath/$tname.ts"
set cfile "$cpath/$cname.ts"
set status [$ts get status]
# Open recording to lock against Auto and Flatten
set recording [open $file r]
if {!$dirdecrypt} {
if {($stime +$delsec) > $ctime} {
log "Waiting for recording $delsec seconds" 1
sleep $($stime +$delsec- $ctime)
set ctime [clock seconds]
}
}
set start [clock milliseconds]
log "starting" 2
# Create links to input in tmp for retrieval
file delete -force "$ipath/$iname.ts"
catch {file link -hard "$ipath/$iname.ts" "[file normalize [file rootname $file].ts]"}
file delete -force "$ipath/$iname.nts"
catch {file link -hard "$ipath/$iname.nts" "[file normalize [file rootname $file].nts]"}
file delete -force "$ipath/$iname.hmt"
catch {file link -hard "$ipath/$iname.hmt" "[file normalize [file rootname $file].hmt]"}
set its [ts fetch $ifile]
# Use link for .nts so updates are visble
file delete -force "$tpath/$tname.nts"
catch {file link -hard "$tpath/$tname.nts" "[file normalize [file rootname $file].nts]"}
# Copy sidecar files and update program title, encryption flag
file copy -force "[file rootname $file].hmt" "$tpath/$tname.hmt"
# Update output hmt to valid, decrypted, ad-detected empty file
set title [$ts get title]
set guidance [$ts get guidance]
exec hmt "-encrypted" "$tpath/$tname.hmt"
exec hmt "-protect" "$tpath/$tname.hmt"
exec hmt "+detectads" "$tpath/$tname.hmt"
exec hmt "+patch8=0x28c:2" "$tpath/$tname.hmt"
set_HMT_durn "$tpath/$tname" $stime 0
set ftime [clock format $stime -format "%Y%m%d%H%M.%S"]
exec touch $tfile -t $ftime
set tts [ts fetch $tfile]
set tfilesize 0 ;# Silence/nsplice cant handle restart midway so force total file retrieval
if {$crop} {
# Set up modified copy of nicesplice to run in pipline if cropping
# title will be copied to output by nicesplice so we can change again after opening pipe
set newtitle [concat $title "-Crop"]
exec hmt "+settitle=${newtitle}" "$tpath/$tname.hmt"
#exec touch "$cpath/$cname.ts" -t $ftime
set cropInput [open "|\
/mod/webif/plugin/detectads/nsplice -in {$tpath/$tname} -out {$cpath/$cname} -stdin |\
awk {\{ print strftime(\"%d/%m/%Y %H:%M:%S NS([pid])-\"), \$0; fflush(); \}} \
>@$::logfd" w]
set cropPids [pid $cropInput]
log "crop pids $cropPids" 2
fconfigure $cropInput -buffering line
sleep 5
} else {set cropInput [open /dev/null w]}
set newtitle [concat $title "-Decrypt"]
exec hmt "+settitle=${newtitle}" "$tpath/$tname.hmt"
if {!$dirdecrypt} {
# Use chaseget for decryption
set decrypt "/mod/bin/chaseget {$ifile} $tfilesize"
} else {
# Use stripts for decryption
set decrypt "/mod/bin/stripts -@@ -d -d {$ipath/$iname} - 2>@$::logfd"
}
set adDetectOutput [open "|\
$decrypt |\
tee -i {$tfile} |\
nice -n 19 ffmpeg -nostats -loglevel fatal -i pipe:0 -vn -sn -ac 2 -f au pipe:1 2>@$::logfd |\
/mod/webif/plugin/detectads/silence $silenceArgs 2>@$::logfd" r]
set adDetectPids [pid $adDetectOutput]
set pids [pid $adDetectOutput]
log "adDetect pids $pids" 2
# cpulimit if program exists
if {$cpulimit > 0 & [file exists /mod/bin/cpulimit]} {
set curppid [lindex $pids 2]
sleep 3; # mustn't be too quick
exec /mod/bin/cpulimit -l $cpulimit -p $curppid &
log "ffmpeg pid $curppid limited to $cpulimit % of cpu"
}
set bookmarks [$tts bookmarks 1]
log "Initial bookmarks: $bookmarks" 2
set totalEndSeconds 0
# Loop processing output from Silence
while {1} {
if {[catch -break -eval -signal -- {gets $adDetectOutput line} msg opts]} {
log "caught: $msg $opts" 2
break
}
log $line 2
if {[eof $adDetectOutput]} {
log "EOF detected" 2
break
}
set startMinutes 0
set startSeconds 0
set endMinutes 0
set endSeconds 0
# is it a cut line?
if {[regexp {^cut@= Cut[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalStartSeconds [expr {$startMinutes * 60 + $startSeconds}]
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
log " ad break found $startMinutes:$startSeconds-$endMinutes:$endSeconds ($totalStartSeconds - $totalEndSeconds) Frames: $startFrame - $endFrame" 0
set_HMT_durn "$tpath/$tname" $stime $totalEndSeconds
# ladd will not add them if they already exist
if {$bmend} {
ladd bookmarks $totalEndSeconds
} else {
# "Invert" first bookmark position to be correct for manually run nicesplice crop (from xyz321)
if {$cropcmd eq " "} {
# First bookmark
if {$totalStartSeconds == 0} {
ladd bookmarks $totalEndSeconds
} else {
ladd bookmarks 0 $totalStartSeconds $totalEndSeconds
}
} else {
ladd bookmarks $totalStartSeconds $totalEndSeconds
}
}
# Update bookmarks and build up crop cmd line as each break is detected.- mymsman 150408
$ts setbookmarks $bookmarks
$tts setbookmarks $bookmarks
set cropline "-cut $($totalStartSeconds *10) $($totalEndSeconds *10)"
lappend cropcmd -cut $($totalStartSeconds *10) $($totalEndSeconds *10)
puts $cropInput $cropline
flush $cropInput
incr numAdBreaks
if {$makethm && $numAdBreaks==1} {
# First ad break and thumbnail creation requested
# Check if it already exists
if {![file exists "$bpath/$bname.thm"]} {
# Doesn't exist create it
if {$totalStartSeconds == 0} {
set offset $($totalEndSeconds + $thmoffset)
} else {
set offset $thmoffset
}
if {$offset < 0} {set offset 0}
set thmstart [clock milliseconds]
system startop thumb $file
$tts mkthm $offset
system endop thumb
set thmend [clock milliseconds]
if {![file exists "$tpath/$tname.thm"]} {
log "Thumbnail creation failed" 0
} else {
log "Thumbnail created at offset $offset in $(($thmend-$thmstart)/1000) seconds" 0
file copy "$tpath/$tname.thm" "$bpath/$bname.thm"
if {$crop} {
file copy "$tpath/$tname.thm" "$cpath/$cname.thm"
}
}
}
}
}
# is it a heartbeat line?
if {[regexp {^status@= HtBeat[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
set cropline "-chkpt $($totalEndSeconds *10)"
puts $cropInput $cropline
flush $cropInput
set_HMT_durn "$tpath/$tname" $stime $totalEndSeconds
log "Hearbeat: Frame $endFrame Time: $endMinutes:$endSeconds Seconds: $totalEndSeconds" 1
}
# is it the End line?
if {[regexp {^status@= End[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
set cropline "-end $($totalEndSeconds *10)"
puts $cropInput $cropline
flush $cropInput
set_HMT_durn "$tpath/$tname" $stime $totalEndSeconds
log "End: Frame $endFrame Time: $endMinutes:$endSeconds Seconds: $totalEndSeconds" 1
break
}
if {$bmsil} {
# is it a Silence? that we are bookmarking for debuging
if {[regexp {^debug@ Silence[^(] *([0-9]+)- *([0-9]+) \( *([0-9]+):([0-9]{2})- *([0-9]+):([0-9]{2})} $line \
wholeMatch \
startFrame \
endFrame \
startMinutes \
startSeconds \
endMinutes \
endSeconds]} {
set totalStartSeconds [expr {$startMinutes * 60 + $startSeconds}]
set totalEndSeconds [expr {$endMinutes * 60 + $endSeconds}]
ladd bookmarks $totalStartSeconds
$ts setbookmarks $bookmarks
$tts setbookmarks $bookmarks
log " Silence found $startMinutes:$startSeconds-$endMinutes:$endSeconds ($totalStartSeconds - $totalEndSeconds) Frames: $startFrame - $endFrame" 0
}
}
}
log "After process loop" 2
close $adDetectOutput
close $cropInput
log "Final bookmarks: $bookmarks" 0
log "$cropcmd" 2
$ts setbookmarks $bookmarks
$tts setbookmarks $bookmarks
# Delete links to input from /mod/tmp
$its delete
# Check that complete file has been retrieved & detected
set ts [ts fetch $file]
set tfilesize [file size $tfile]
set filesize [file size $file]
set missing $($filesize -$tfilesize)
set lengtherr 0
set dadflag "+detectads"
set stime [$ts get start]
set etime [$ts get end]
set durn $($etime-$stime)
set misstime $(round(abs($missing)/($filesize/$durn)))
set misdetect $(abs($durn-$totalEndSeconds))
if {$missing != 0} {
# Length error in decryption
set lengtherr 1
set warning "Incomplete data retrieval $missing bytes missing ([clock format $misstime -format %T])"
system notify "DetectAds $file $warning"
log "$file $warning" 0
set newtitle "$title -Len err (decrypt)"
if {$misstime >= $misrdsec} {
set qtime [clock seconds]
if {$etime > $qtime} {set qtime $etime}
set qtime $($qtime + 900)
incr retrynumb
if {$retrynumb < $retmax} {
set newQid [::detectads::queue $ts $qtime $retrynumb]
system notify "Queing $file for retry of detectads due to significant file length error"
log "Queing $file for retry of detectads due to significant file length error" 0
log "Qid $newQid target start [clock format $qtime -format %T]" 1
set dadflag "-detectads"
set tempQid 0
set retcode "DEFER"
} else {
system notify "Retry limit exceded for $file cant process file"
log "Retry limit exceded for $file cant process file" 0
set retcode "FAILED"
}
} else {
set dadflag "+detectads"
}
} else {
if {$misdetect > $misdetsec} {
# Length error in dectection
set lengtherr 1
set warning "Detection Length error, Bookmarks may be upto [clock format $misdetect -format %T] out"
if {$misdetect > $misdetalarm} {
system notify "DetectAds $file $warning"
}
log "$file $warning" 0
set newtitle "$title -Len err ([clock format $misdetect -format %T])"
}
}
if {$lengtherr == 0} {
# All OK (as far as we can tell)
set newtitle "Done"
exec hmt $dadflag "$bpath/$bname.hmt"
close $recording
if {$delorig && ![system inuse $file]} { # Delete original file no longer wanted
if {[safe_delete $file detectads]} {
log "$file deleted" 0
if {$crop} {
if {![system inuse $cfile]} { # Rename crop file to original if not in use
exec hmt "+settitle=$title" "$cpath/$cname.hmt"
ts renamegroup "$cfile" "$bname"
}
if {![system inuse $tfile]} { # Delete decrypt file no longer needed
$tts delete
log "$tfile deleted" 0
}
} else {
if {![system inuse $tfile]} { # Rename decrypt file to original if not in use
exec hmt "+settitle=$title" "$tpath/$tname.hmt"
if {$tpath ne $tgtpath} { # Move to correct directory
$tts move $tgtpath
}
ts renamegroup "$tgtpath/$tname.ts" "$bname"
}
}
} else {
log "$file safe_delete failed" 0
}
} else { # Keeping original, dont rename
if {$crop} {
if {![system inuse $tfile]} { # Delete decrypt file no longer needed
$tts delete
log "$tfile deleted" 0
}
} else {
if {$tpath ne $tgtpath} { # Move decrypt to correct directory
$tts move $tgtpath
}
}
}
} else {
# Somethings amiss with file length, keep original and -crop, delete -dec
if {![system inuse $tfile]} { # Delete decrypt file no longer needed
$tts delete
log "$tfile deleted" 0
}
exec hmt $dadflag "$bpath/$bname.hmt"
if {$crop} {
exec hmt "+settitle=$newtitle" "$cpath/$cname.hmt"
}
close $recording
}
if {$tempQid} {
# remove temporary entryt from the queue
log "Removing item $tempQid ($file) from the queue" 1
{queue delete_by_id} $tempQid
}
set elapsedSeconds [elapsed $start]
set elapsedTime [clock format $(round($elapsedSeconds)) -format "%H:%M:%S"]
log "done...processed $file in ${elapsedSeconds}s $elapsedTime - $numAdBreaks ad breaks detected" 0
set retmsg "$numAdBreaks ad breaks detected, $warning"
system endop $statustok
release_lock $file
log "=============================================================" 1
set ::auto::loglevel ::autologlevel
return [list $retcode $retmsg $qtime]
}
proc set_HMT_durn {hmtfn start durn} {
# Update recording end & stored recording time in hmt file
exec hmt "+patch32=0x284:$($durn+$start)" "$hmtfn.hmt"
exec hmt "+patch32=0x288:$durn" "$hmtfn.hmt"
}