video2d-2x/scripts/extract.sh
2020-11-14 21:02:26 +03:00

126 lines
3.8 KiB
Bash

#!/bin/bash
# This file is part of video2d-2x.
#
# video2d-2x is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
function extension_by_codec () # $1: Codec
{
local Ext=""
for Mux in muxer demuxer
do
# Where is my json?!
Ext=$(
ffprobe -v quiet -h $Mux="$1" | \
grep 'Common extensions:' | \
sed -r 's|^.+: ([^,\.]+).+|\1|')
if [[ -n "$Ext" ]]; then
echo "$Ext"
break
fi
done
}
function extract_attachments ()
{
pushd "$AttachmentsDir"
ffmpeg -hide_banner -dump_attachment:t "" -i "$InputFile"
# There is no error checking,
# because ffmpeg always throws an error:
# "At least one output file must be specified",
# although it successfully saves attachments.
popd
}
function extract_chapters ()
{
# TODO: Convert $ChaptersJson to mkv-compatible format?
echo "DUMMY"
}
function extract_framedurations () # $1: stream index
{
local FileIndex=0
echo "ffconcat version 1.0" > "$FrameDurationList"
while read Line
do
if echo "$Line" | grep -qF 'pts_time='; then
((FileIndex++))
printf "file \'./$(basename $FramesUpscaledDir)/%06d.png\'\n" "$FileIndex" >> "$FrameDurationList"
echo "inpoint $(echo "$Line" | grep -Po '\d+\.\d+')" >> "$FrameDurationList"
elif echo "$Line" | grep -qF 'duration_time='; then
echo "duration $(echo "$Line" | grep -Po '\d+\.\d+')" >> "$FrameDurationList"
fi
done < <(ffprobe -v quiet -show_entries packet=pts_time,duration_time -select_streams "$Index" "$InputFile")
}
if [[ -z "$1" ]]; then
echo "You must specify the video file"
exit "$PARAMETER_ERROR"
else
InputFile=$(readlink -e "$1")
fi
if ! [[ -r "$InputFile" ]]; then
echo "Read file error: \"$InputFile\""
exit "$FILE_READ_ERROR"
fi
rm -rf "$AudioDir"; mkdir -p "$AudioDir"
rm -rf "$VideoDir"; mkdir -p "$VideoDir"
rm -rf "$SubtitlesDir"; mkdir -p "$SubtitlesDir"
rm -rf "$ChaptersDir"; mkdir -p "$ChaptersDir"
rm -rf "$AttachmentsDir"; mkdir -p "$AttachmentsDir"
ffprobe -v quiet -print_format json -show_streams "$InputFile" > "$StreamsJson"
ffprobe -v quiet -print_format json -show_format "$InputFile" > "$FormatJson"
ffprobe -v quiet -print_format json -show_chapters "$InputFile" > "$ChaptersJson"
StreamCount=$(jq -r '.format.nb_streams' "$FormatJson")
for (( Index=0; Index < StreamCount; Index++ ))
do
Type=$(jq -r ".streams[$Index].codec_type" "$StreamsJson")
Codec=$(jq -r ".streams[$Index].codec_name" "$StreamsJson")
Extension=$(extension_by_codec "$Codec")
if [[ -z "$Extension" ]]; then
echo "No extension for codec \"$Codec\""
exit "$NO_EXTENSION_FOR_CODEC"
fi
case "$Type" in
video )
extract_framedurations "$Index"
ffmpeg -hide_banner -i "$InputFile" -map "0:$Index" -c:v copy "$VideoDir/$Index.$Extension"
if [[ "$?" != 0 ]]; then exit "$EXTRACT_AUDIO_ERROR"; fi ;;
audio )
ffmpeg -hide_banner -i "$InputFile" -map "0:$Index" -c:a copy "$AudioDir/$Index.$Extension"
if [[ "$?" != 0 ]]; then exit "$EXTRACT_VIDEO_ERROR"; fi ;;
subtitle )
ffmpeg -hide_banner -i "$InputFile" -map "0:$Index" "$SubtitlesDir/$Index.$Extension"
if [[ "$?" != 0 ]]; then exit "$EXTRACT_SUBTITLE_ERROR"; fi ;;
attachment )
continue ;;
* )
echo "Unknown codec type: \"$Type\""
exit "$UNKNOWN_CODEC_TYPE_ERROR" ;;
esac
done
extract_attachments