core sh scripts for transcoding to h264 in mkv
This commit is contained in:
parent
763f589be1
commit
81912155c1
18
ffmpeg-cut-to-mkv.sh
Executable file
18
ffmpeg-cut-to-mkv.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -a
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
file=${file:-"$A1"}
|
||||||
|
recordingsdir=${A2:-"/var/lib/mythtv/recordings"}
|
||||||
|
chanid=$1
|
||||||
|
starttimeutc=$2
|
||||||
|
title=${title:-"$A3"}
|
||||||
|
subtitle=${subtitle:-"$A4"}
|
||||||
|
season=${season:-"$A5"}
|
||||||
|
episode=${episode:-"$A6"}
|
||||||
|
|
||||||
|
ffmpeg-cut-list0.sh $chanid $starttimeutc
|
||||||
|
ffmpeg-to-mkv.sh $chanid $starttimeutc
|
||||||
|
|
||||||
|
exit $?
|
38
ffmpeg-to-mkv-marks.awk
Normal file
38
ffmpeg-to-mkv-marks.awk
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
BEGIN {
|
||||||
|
RS="\n"
|
||||||
|
ORS="\n"
|
||||||
|
FS="[=/]"
|
||||||
|
mark["width"]=30
|
||||||
|
mark["height"]=31
|
||||||
|
mark["avg_frame_rate"]=32
|
||||||
|
mark["duration"]=33
|
||||||
|
mark["total_frames"]=34
|
||||||
|
}
|
||||||
|
# A typical record looks like: (I don't know how to remove duplicates)
|
||||||
|
# width=1280
|
||||||
|
# height=720
|
||||||
|
# avg_frame_rate=60000/1001
|
||||||
|
# duration=719.385322
|
||||||
|
# width=1280
|
||||||
|
# height=720
|
||||||
|
# avg_frame_rate=60000/1001
|
||||||
|
# duration=719.385322
|
||||||
|
# --
|
||||||
|
/width|height|avg_frame_rate|duration/{
|
||||||
|
if($1 ~ /avg_frame_rate|duration/) {
|
||||||
|
if (NF == 3 && $2 ~ /[0-9]+/ && $3 ~ /[1-9][0-9.]*/) {
|
||||||
|
#print $2 " " $3
|
||||||
|
a[$1] = int($2/$3*1000+0.5)
|
||||||
|
} else {
|
||||||
|
a[$1] = int($2*1000+0.5)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
a[$1] = $2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
a["total_frames"]=int(a["duration"]*a["avg_frame_rate"]/1000/1000+0.5)
|
||||||
|
for (k in a) {
|
||||||
|
printf "<mark data=\"%s\" frame=\"0\" type=\"%s\"/>\n", a[k], mark[k]
|
||||||
|
}
|
||||||
|
}
|
33
ffmpeg-to-mkv-seektable.awk
Normal file
33
ffmpeg-to-mkv-seektable.awk
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
BEGIN {
|
||||||
|
RS="--\n"
|
||||||
|
ORS="\n"
|
||||||
|
FS="[=\n]"
|
||||||
|
frm=0
|
||||||
|
offset=0
|
||||||
|
}
|
||||||
|
# A typical record looks like:
|
||||||
|
# pkt_pts_time=166.725833
|
||||||
|
# pkt_pos=596336
|
||||||
|
# pict_type=I
|
||||||
|
# coded_picture_number=13
|
||||||
|
# interlaced_frame=0
|
||||||
|
# --
|
||||||
|
{
|
||||||
|
pkt_pts_time=int($2*1000+0.5)
|
||||||
|
pkt_pos=$4
|
||||||
|
frame=$8+offset
|
||||||
|
if (frm==0) {
|
||||||
|
startpts=pkt_pts_time
|
||||||
|
# a bug? in ffprobe makes the frame numbers deficient by 2 after frame 0
|
||||||
|
# but this does not seem to affect mkv containers made by ffmpeg?
|
||||||
|
if (ending != "mkv") {
|
||||||
|
offset=2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frm=1
|
||||||
|
pkt_pts_time=pkt_pts_time-startpts
|
||||||
|
# <seek data="381841724" frame="9570" type="9"/>
|
||||||
|
# <seek data="159660" frame="9570" type="33"/>
|
||||||
|
print "<seek type=\"9\" data=\"" pkt_pos "\" frame=\"" frame "\"/>"
|
||||||
|
print "<seek type=\"33\" data=\"" pkt_pts_time "\" frame=\"" frame "\"/>"
|
||||||
|
}
|
55
ffmpeg-to-mkv.sh
Executable file
55
ffmpeg-to-mkv.sh
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
file=${file:-"$A1"}
|
||||||
|
recordingsdir=${A2:-"/var/lib/mythtv/recordings"}
|
||||||
|
chanid=$1
|
||||||
|
starttimeutc=$2
|
||||||
|
title=${title:-"$A3"}
|
||||||
|
subtitle=${subtitle:-"$A4"}
|
||||||
|
season=${season:-"$A5"}
|
||||||
|
episode=${episode:-"$A6"}
|
||||||
|
|
||||||
|
ending=$(echo $file | awk -v FS='.' '{print $NF}')
|
||||||
|
outfile=${file/%.${ending}/.mkv}
|
||||||
|
debug=${debug:-"eval"}
|
||||||
|
ffmpeg=${ffmpeg:-"/usr/local/bin/ffmpeg"}
|
||||||
|
destdir=${destdir:-"${recordingsdir/recordings/videos\/transcode}"}
|
||||||
|
#chanid=${file:0:4}
|
||||||
|
#starttimeutc=${file:5:13}
|
||||||
|
if test $chanid -eq 1031; then
|
||||||
|
lang="fre"
|
||||||
|
else
|
||||||
|
lang="en"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmd="ionice -c 3 $ffmpeg -y -i ${recordingsdir}/${file} -f lavfi -i movie=${recordingsdir}/${file}[out0+subcc] -preset slow -crf 21 -map 0 -map -0:d -codec:a copy -map 1:s -map_metadata 1:s:0 -metadata:s:s \"language=${lang}\" -g 60 -keyint_min 30 -metadata \"title=${title}\" -metadata \"subtitle=${subtitle}\" -metadata \"season=${season}\" -metadata \"episode=${episode}\" -metadata \"service_name=$0\" ${destdir}/${outfile}"
|
||||||
|
|
||||||
|
echo Information:
|
||||||
|
echo chanid: $chanid
|
||||||
|
echo starttimeutc: $starttimeutc
|
||||||
|
echo file: $file
|
||||||
|
echo outfile: $outfile
|
||||||
|
echo recordingsdir: $recordingsdir
|
||||||
|
echo title: $title
|
||||||
|
echo subtitle: $subtitle
|
||||||
|
echo season: $season
|
||||||
|
echo episode: $episode
|
||||||
|
echo ending: $ending
|
||||||
|
echo debug: $debug
|
||||||
|
echo ffmpeg: $ffmpeg
|
||||||
|
echo destdir: $destdir
|
||||||
|
echo cmd: $cmd
|
||||||
|
|
||||||
|
$debug $cmd
|
||||||
|
exitstatus=$?
|
||||||
|
|
||||||
|
if ! test $exitstatus -eq 0; then
|
||||||
|
exit $exitstatus
|
||||||
|
fi
|
||||||
|
touch --reference="${recordingsdir}/${file}" "${destdir}/${outfile}"
|
||||||
|
myth-update-basename.sh $chanid $starttimeutc $outfile
|
||||||
|
myth-rebuild-seektable.sh $chanid $starttimeutc
|
||||||
|
|
||||||
|
exit $?
|
109
myth-rebuild-seektable.sh
Executable file
109
myth-rebuild-seektable.sh
Executable file
@ -0,0 +1,109 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
chanid=$1
|
||||||
|
starttime=$2
|
||||||
|
if test -z "$3"; then
|
||||||
|
workdir=${workdir:-"/tmp"}
|
||||||
|
else
|
||||||
|
workdir=$3
|
||||||
|
fi
|
||||||
|
fileroot="${chanid}_${starttime}"
|
||||||
|
ffprobe=${ffprobe:-"ionice -c 3 ffprobe"}
|
||||||
|
ffmpeg_to_mkv_seektable_awk=${ffmpeg_to_mkv_seektable_awk:-"/usr/local/bin/ffmpeg-to-mkv-seektable.awk"}
|
||||||
|
ffmpeg_to_mkv_marks_awk=${ffmpeg_to_mkv_marks_awk:-"/usr/local/bin/ffmpeg-to-mkv-marks.awk"}
|
||||||
|
# testing only
|
||||||
|
destdir=${destdir:-"/var/lib/mythtv/recordings"}
|
||||||
|
outfile=${outfile:-"$(ls $destdir/${fileroot}.{mpg,ts,mkv,mp4} 2>/dev/null | sort -u | head -n 1)"}
|
||||||
|
ending=$(echo "$outfile" | awk -v FS='.' '{print $NF}')
|
||||||
|
|
||||||
|
if test -z "$outfile"; then
|
||||||
|
echo No recording file found with root $fileroot and ending mpg, ts, mkv or mp4
|
||||||
|
exit 7
|
||||||
|
fi
|
||||||
|
if ! test -r "$outfile"; then
|
||||||
|
echo Recording file $outfile is not readable.
|
||||||
|
exit 8
|
||||||
|
else
|
||||||
|
outfile="$(basename $outfile)"
|
||||||
|
fi
|
||||||
|
if test -z "$ending"; then
|
||||||
|
echo Did not find file ending. Stop.
|
||||||
|
exit 9
|
||||||
|
fi
|
||||||
|
|
||||||
|
function get_keyframe_data {
|
||||||
|
key_frame_data=$workdir/${outfile}.2.txt
|
||||||
|
$ffprobe -v error -select_streams v:0 -show_entries frame=pict_type,coded_picture_number,pkt_pos,pkt_pts_time,interlaced_frame:side_data=nil -print_format default=noprint_wrappers=1 -i ${destdir}/${outfile} | grep --context=2 'pict_type=I' | awk -v ending="${ending}" -f $ffmpeg_to_mkv_seektable_awk > $key_frame_data
|
||||||
|
|
||||||
|
exitstatus=$?
|
||||||
|
if ! test $exitstatus -eq 0; then
|
||||||
|
exit $exitstatus
|
||||||
|
fi
|
||||||
|
if ! test -r $key_frame_data; then
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function get_markup_data {
|
||||||
|
markup_data=$workdir/${outfile}.3.txt
|
||||||
|
$ffprobe -v error -show_format -show_streams -select_streams v:0 -show_entries stream=width,height,avg_frame_rate:format=duration -print_format default -i ${destdir}/${outfile} | awk -f $ffmpeg_to_mkv_marks_awk > $markup_data
|
||||||
|
|
||||||
|
exitstatus=$?
|
||||||
|
if ! test $exitstatus -eq 0; then
|
||||||
|
exit $exitstatus
|
||||||
|
fi
|
||||||
|
if ! test -r $markup_data; then
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function set_markup_xml {
|
||||||
|
get_keyframe_data
|
||||||
|
get_markup_data
|
||||||
|
markup_xml=$workdir/${outfile}.xml
|
||||||
|
cat <<EOF> $markup_xml
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<metadata>
|
||||||
|
<item>
|
||||||
|
<markup>
|
||||||
|
EOF
|
||||||
|
cat $key_frame_data $markup_data >> $markup_xml
|
||||||
|
cat <<EOF >> $markup_xml
|
||||||
|
</markup>
|
||||||
|
</item>
|
||||||
|
</metadata>
|
||||||
|
EOF
|
||||||
|
exitstatus=$?
|
||||||
|
if ! test $exitstatus -eq 0; then
|
||||||
|
exit $exitstatus
|
||||||
|
fi
|
||||||
|
if ! test -r $markup_data; then
|
||||||
|
exit 5
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
function rebuild_seektable {
|
||||||
|
if test "$ending" = "mpg" -o "$ending" = "ts"; then
|
||||||
|
mythcommflag --chanid $chanid --starttime $starttime --rebuild
|
||||||
|
else
|
||||||
|
# file is mkv or mp4, so use ffprobe and mythutil
|
||||||
|
set_markup_xml && mythutil --quiet --chanid $chanid --starttime $starttime --setmarkup $markup_xml
|
||||||
|
# need to update filesize, too, since markup does not contain this
|
||||||
|
myth-update-basename.sh $chanid $starttime $outfile
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for t in skiplist cutlist seektable; do
|
||||||
|
mythutil --chanid $chanid --starttime $starttime --clear$t
|
||||||
|
done
|
||||||
|
rebuild_seektable
|
||||||
|
|
||||||
|
|
||||||
|
# function clear_seeks_from_recordedmarkup {
|
||||||
|
# markupfile="$workdir/$1.xml"
|
||||||
|
# mythutil --quiet --chanid $chanid --starttime $starttime --getmarkup $markupfile && sed -ri -e '/seek/{d}; /mark/{/type="3[0-2]|1[0-9]"/{p}; d};' $markupfile && mythutil --quiet --chanid $chanid --starttime $starttime --setmarkup $markupfile
|
||||||
|
# }
|
||||||
|
# function remove_start_prog {
|
||||||
|
# markupfile="$workdir/$1.xml"
|
||||||
|
# mythutil --quiet --chanid $chanid --starttime $starttime --getmarkup $markupfile && sed -ri -e '/type="40"/{d}' $markupfile && mythutil --quiet --chanid $chanid --starttime $starttime --setmarkup $markupfile
|
||||||
|
# }
|
||||||
|
|
||||||
|
exit $?
|
12
myth-update-basename.sh
Executable file
12
myth-update-basename.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
chanid=$1
|
||||||
|
starttimeutc=$2
|
||||||
|
basename=$3
|
||||||
|
filesize=$(stat --printf="%s" $destdir/$basename)
|
||||||
|
dir="$HOME/.mythtv/"
|
||||||
|
config="config.xml"
|
||||||
|
mysql_password=$(awk -v FS='[<>]' '/Password/{print $3}' $dir/$config)
|
||||||
|
printf "update recorded set basename='%s', filesize='%s' where chanid=%s and starttime=%s;" $basename $filesize $chanid $starttimeutc | mysql --user=${USER} --password=${mysql_password} mythconverg
|
||||||
|
|
Loading…
Reference in New Issue
Block a user