Sum*_*ukh 7 command-line video nautilus-script
我一直在使用mkvmerge
合并视频文件和字幕,我正在使用以下命令
mkvmerge -o output.mkv video.mp4 subtitles.srt
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,但您可能会猜到这真的很慢
这是一个漫长的过程。
我想要的理想情况。
mkv
扩展名的原始文件的名称重命名合并的文件这不需要递归,我不希望我的硬盘创建和删除 100 个文件。电影文件和字幕文件通常具有相同的名称,但有时会在字幕文件中固定“_en”后缀。如果您有其他方法可以做到这一点,我也同意。
我决定获得一些使用 Bash 的经验并编写了以下脚本,该脚本具有以下功能:
mkvmerge
将视频与字幕文件合并,也用于notify-send
在 GUI 中显示一些消息。它还用于gvfs-trash
移动用户垃圾文件夹中的文件。notify-send
命令存在于脚本主体中。剧本:
#!/bin/bash -e
# Check if all tools are available
[ -x /usr/bin/notify-send ] || (echo "Please, install 'notify-send'"; exit 1)
[ -x /usr/bin/mkvmerge ] || (echo "Please, install 'mkvmerge'"; exit 1)
# Allowed video and subtitle file extensions
EXT_VIDEO=("mp4 avi mpg mov mkv wmv")
EXT_SUB=("sub str srt vtt")
# Files, which names contains some of next strings will be removed in auto mode
FILTER=("sample Sample SAMPLE")
# Log file
MERGE_LOG="/tmp/merge-video-sub.log"
echo > "$MERGE_LOG"
#
# Functions
#
function get-video-and-sub-file-names {
# Get the names of the video and subtitle files and move the rest of the files into the Backup directory
for ((i=0; i<${#FILE_LIST[@]}; i++)); do
FILE_NAME="${FILE_LIST[$i]%.*}"
FILE_EXT="${FILE_LIST[$i]##*.}"
if [[ "${EXT_SUB[@]}" == *"$FILE_EXT"* ]]; then
SUB_FULL_FILE_NAME="${FILE_LIST[$i]}"
SUB_FILE_NAME="${FILE_NAME}"
SUB_FILE_EXT="${FILE_EXT}"
elif [[ "${EXT_VIDEO[@]}" == *"$FILE_EXT"* ]]; then
VIDEO_FULL_FILE_NAME="${FILE_LIST[$i]}"
VIDEO_FILE_NAME="${FILE_NAME}"
VIDEO_FILE_EXT="${FILE_EXT}"
else
# We need 'find' to manipulate only with files, because "$BACKUP_DIR" is in the queue
find ./* -maxdepth 0 -type f -name "${FILE_LIST[$i]}" -exec mv "{}" "$BACKUP_DIR" \; -exec echo -e "The file {} was REMOVED.\n" >> "$MERGE_LOG" \;
fi
done
}
function get-the-content-of-the-current-directory {
# Get the content of the current directory
shopt -s nullglob
FILE_LIST=(*)
shopt -u nullglob
}
function mkvmerge-video-and-sub-files {
# Create merged file
mkvmerge -o "$OUTPUT_FILE" "$VIDEO_FULL_FILE_NAME" "$SUB_FULL_FILE_NAME"
sleep 3
}
#
# Scenario 1: If exactly two files are selected in Nautilus! Then check if they are 1 video and 1 subtitle files, if yes - merge and remove them
# Scenario 2: Else run the standard procedure
#
# Get the files, selected in Nautilus as file list. Use next command to check the result: notify-send "MESSAGE" "`echo -e "${#FILE_LIST[@]}"; printf '%s\n' "${FILE_LIST[@]}"`"
IFS_BAK=$IFS
IFS=$'\t\n'
FILE_LIST=($NAUTILUS_SCRIPT_SELECTED_FILE_PATHS)
IFS=$IFS_BAK
if [ "${#FILE_LIST[@]}" -eq "2" ]
then # Scenario 1
# Get the names of the video and subtitle files
get-video-and-sub-file-names
if [[ "${EXT_SUB[@]}" == *" $SUB_FILE_EXT "* ]] && [[ "${EXT_VIDEO[@]}" == *" $VIDEO_FILE_EXT "* ]]
then
notify-send "OK" "`echo -e "The following files will be MERGED and MOVED to trash:"; printf '\t-\ %s\n' "${FILE_LIST[@]##*/}"`"
# Construct the name of the merged file.
OUTPUT_FILE="${VIDEO_FILE_NAME}.sub.mkv"
# Merge the files
mkvmerge-video-and-sub-files
# Move video and subtitle files into user's trash directory and create trash infofile
if [ -f "$OUTPUT_FILE" ]
then
gvfs-trash "$VIDEO_FULL_FILE_NAME"
gvfs-trash "$SUB_FULL_FILE_NAME"
notify-send "OK" "`echo -e "THE NAME OF THE NEW MERGED FILE IS:\n${OUTPUT_FILE##*/}"`"
else
notify-send "ERROR 1" "`echo "Something went wrong!"`"
fi
else
notify-send "ERROR" "`echo -e "\n\t\nTo use this function, please select exactly:\n\t- 1 video file and\n\t- 1 subtitle file!\n\t\nYou are selected these files:"; printf '\t-\ %s\n' "${FILE_LIST[@]##*/}"`"
fi
else # Scenario 2
# Get the current directory name
DIR_NAME="${PWD##*/}"
# Create Backup sub-directory
BACKUP_DIR="${DIR_NAME}.backup"
[ -d "${BACKUP_DIR}" ] || mkdir "$BACKUP_DIR" && echo "The directory $BACKUP_DIR was CREATED.\n" > "$MERGE_LOG"
# Move all sub-directories into the Backup directory
shopt -s dotglob
find ./* -maxdepth 0 -type d ! -name "*$BACKUP_DIR*" -prune -exec mv "{}" "$BACKUP_DIR" \; -exec echo "The directory {} was REMOVED.\n" >> "$MERGE_LOG" \;
shopt -u dotglob
# Move all files and folders, whose names contains a string, that exists in $FILTER[@]
for f in $FILTER; do
shopt -s dotglob
find ./* -maxdepth 0 ! -name "*$BACKUP_DIR*" -type f -name "*$f*" -exec mv "{}" "$BACKUP_DIR" \; -exec echo "The file {} was REMOVED.\n" >> "$MERGE_LOG" \;
shopt -u dotglob
done
# Get the entire content of the current directory
get-the-content-of-the-current-directory
# Get the names of the video and subtitle files and move the rest of the files into the Backup directory
get-video-and-sub-file-names
# Construct the name of the merged file. It could be based on the parent directory or on the video file name Make your choice and comment/uncomment next lines
#OUTPUT_FILE="${VIDEO_FILE_NAME}.sub.mkv"
OUTPUT_FILE="${DIR_NAME}.sub.mkv"
# Get the entire content of the current directory after the filtering
get-the-content-of-the-current-directory
echo -e "$(cat $MERGE_LOG)" && notify-send "OK" "`echo -e "$(cat $MERGE_LOG)"`" && echo > "$MERGE_LOG"
# Check the current structure of the directory
if [ "${#FILE_LIST[@]}" -ne "3" ]; then
echo "The content structure must consists of next 3 items:" > "$MERGE_LOG"
echo "\t- 1 movie file,\n\t- 1 subtitle file and\n\t- 1 backup directory." >> "$MERGE_LOG"
echo "\n\t\nThe current number of contained items is ${#FILE_LIST[@]}." >> "$MERGE_LOG" && echo >> "$MERGE_LOG"
echo "\n\t\nPLEASE RESOLVE THIS MANUALLY!" >> "$MERGE_LOG"
echo -e "$(cat $MERGE_LOG)" && notify-send "ERROR" "`echo -e "$(cat $MERGE_LOG)"`"
else
echo "The directory structure looks good, is contains ${#FILE_LIST[@]} items." > "$MERGE_LOG"
echo " - The source VIDEO file is: ${VIDEO_FULL_FILE_NAME::21}... .${VIDEO_FULL_FILE_NAME##*.}" >> "$MERGE_LOG"
echo " - The source SUB file is: ${SUB_FULL_FILE_NAME::25}... .${SUB_FULL_FILE_NAME##*.}" >> "$MERGE_LOG"
echo "They has been merged and removed!" | tr /a-z/ /A-Z/ >> "$MERGE_LOG"
# Merge the files
mkvmerge-video-and-sub-files
# Move video and subtitle files into the Backup directory
mv "$VIDEO_FULL_FILE_NAME" "$BACKUP_DIR"
mv "$SUB_FULL_FILE_NAME" "$BACKUP_DIR"
# Move the Backup directory to trash and create trash infofile
if [ -f "$OUTPUT_FILE" ]; then
gvfs-trash "$BACKUP_DIR"
echo "\n\t\nThe Backup directory has been MOVED to Trash!\n\t\n" >> "$MERGE_LOG"
echo "The name of the new merged file is:" | tr /a-z/ /A-Z/ >> "$MERGE_LOG"
echo "${OUTPUT_FILE##*/}" >> "$MERGE_LOG"
echo -e "$(cat $MERGE_LOG)" && notify-send "OK" "`echo -e "$(cat $MERGE_LOG)"`"
else
echo "Something went wrong!" && notify-send "ERROR 2" "`echo "Something went wrong!"`"
fi
fi
fi
rm "$MERGE_LOG"
exit 1
Run Code Online (Sandbox Code Playgroud)
设置:
创建可执行文件并将上述内容粘贴到其中。让我们调用这个文件merge-video-sub
:
touch merge-video-sub
chmod +x merge-video-sub
nano merge-video-sub
Run Code Online (Sandbox Code Playgroud)ln -s
将此文件复制(或)到文件夹中~/.local/share/nautilus/scripts
,使其可用作当前用户的 Nautilus 脚本。
目前我找不到如何使它在系统范围内作为 Nautilus 脚本可用的方法。
将文件复制到~/bin
(并添加export PATH=$PATH:~/bin
到~/.bashrc
if的底部)以使其可用作当前用户的 shell 命令。
将文件复制到其中/usr/local/bin
以使其可用作 shell 命令系统范围。
简短的方法是curl
将脚本从我的 PasteBin直接放入nautilus/scripts
文件夹:
curl https://pastebin.com/raw/HrLTibuR | sed -e 's/\r$//' > $HOME/.local/share/nautilus/scripts/merge-video-sub
chmod +x $HOME/.local/share/nautilus/scripts/merge-video-sub
Run Code Online (Sandbox Code Playgroud)演示:
补充参考: