Created
November 16, 2020 10:24
-
-
Save aadm/1910d06a749412a0b90db51d120ffa70 to your computer and use it in GitHub Desktop.
Bash script to transcode video and audio clips to Davinci Resolve accepted codec.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#------------------------------------------------------------------------------------- | |
# Convert all clips in a directory to Davinci Resolve compatible format. | |
# Will work on both audio and video files. | |
# Creates two subdirectories in current directory: | |
# - ORIGINAL (where the input files will be moved after conversion) | |
# - TRANSCODED (where the converted files will be created) | |
# | |
# Originally I used as output format prores which made the script much | |
# simpler but the output files were massive. I then switched to DNxHD/DNxHR format | |
# which is far more finnicky as the files need to be encoded with specific bitrates | |
# according to the frameratem but the advantage is in having smaller files. | |
# Another format which I also tried is simple mpeg4 which is as easy to use as prores | |
# and the resulting size is very small, but the downside is the degraded quality. | |
# I haven't done any rigorous testing on this, so feel free to change or modify | |
# the script below and let me know. | |
# | |
# Notes: | |
# - needs ffmpeg and exiftool available in path; | |
# - exiftool is used at end of the conversion to copy the "CreateDate" tag | |
# to "FileModifyDate" tag otherwise Resolve doesn't pick up the correct | |
# creation date (I use the sort on creation date to put order in the media view). | |
# - see table at the end of the script for information on the DNxHD format and | |
# accepted framerate; | |
# - the low-disk-usage codec can be activated by replacing all the if-then blocks | |
# and simply put "-vcodec mpeg4" in the ffmpeg options; maybe an option can be | |
# added to allow the user to switch to this codec if quality preservation is not | |
# paramount (maybe some further tests are needed). | |
#------------------------------------------------------------------------------------- | |
counter=0 | |
ORIGINAL_DIR="ORIGINAL" | |
TRANSCODED_DIR="TRANSCODED" | |
if [ ! -d "$ORIGINAL_DIR" ]; then | |
mkdir $ORIGINAL_DIR | |
fi | |
if [ ! -d "$TRANSCODED_DIR" ]; then | |
mkdir $TRANSCODED_DIR | |
fi | |
current_time=$(date +"%Y/%m/%d %H:%M:%S") | |
echo "---> START $current_time (working directory: $PWD)" | |
videotypes=("m4v" "mp4" "mov") | |
audiotypes=("flac" "mp3" "aac" "wma" "ogg" "oga" "mogg" "raw") | |
OIFS="$IFS" | |
for extaudio in "${audiotypes[@]}"; do | |
IFS=$'\n' | |
for file in `find . -maxdepth 1 -type f -iname "*.${extaudio}" -exec basename {} \;`; do | |
counter=$[$counter +1] | |
echo "---> [$counter] $file TRANSCODING TO ${file%.*}-PCM.wav" | |
IFS="$OIFS" | |
ffmpeg -i "$file" -hide_banner -acodec pcm_s16le "$TRANSCODED_DIR/${file%.*}-PCM.wav" | |
IFS=$'\n' | |
mv "$file" -t $ORIGINAL_DIR | |
done | |
done | |
IFS="$OIFS" | |
OIFS="$IFS" | |
for ext in "${videotypes[@]}"; do | |
IFS=$'\n' | |
for file in `find . -maxdepth 1 -type f -iname "*.${ext}" -exec basename {} \;`; do | |
counter=$[$counter +1] | |
size=$(exiftool -v0 -short3 -imagesize $file) | |
framerate=$(exiftool -v0 -short3 -videoframerate $file) | |
bitrate=$(exiftool -v0 -short3 -avgbitrate $file) | |
codec=$(exiftool -v0 -short3 -compressorname $file) | |
if [[ $size == "3840x2160" ]]; then | |
suffix='-DNxHR' | |
echo ".....transcoding input 4K file to DNxHR codec with profile HQ" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -profile:v dnxhr_hq -acodec pcm_s16le -pix_fmt yuv422p' | |
elif [[ $size == "1920x1080" ]]; then | |
suffix='-DNxHD' | |
if [[ ${framerate} == "23.967" ]]; then | |
echo ".....transcoding HD to DNxHD bitrate 36M, fps=23.967" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -b:v 36M -acodec pcm_s16le -r 24000/1001 -pix_fmt yuv422p' | |
elif [[ ${framerate} == "25" ]]; then | |
echo ".....transcoding HD to DNxHD bitrate 36M, fps=25" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -b:v 36M -acodec pcm_s16le -pix_fmt yuv422p' | |
elif [[ ${framerate} == "29.97" ]]; then | |
echo ".....transcoding HD to DNxHD bitrate 45M, fps=29.97" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -b:v 45M -acodec pcm_s16le -r 30000/1001 -pix_fmt yuv422p' | |
elif [[ ${framerate} == "50" ]]; then | |
echo ".....transcoding HD to DNxHD bitrate 75M, fps=50" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -b:v 75M -acodec pcm_s16le -r 60000/1001 -pix_fmt yuv422p' | |
elif [[ ${framerate} == "59.94" ]]; then | |
echo ".....transcoding HD to DNxHD bitrate 90M, fps=59.94" | |
options='-hide_banner -map_metadata 0 -vcodec dnxhd -b:v 90M -acodec pcm_s16le -r 60000/1001 -pix_fmt yuv422p' | |
else | |
echo ".....input fps is not standard (23.967, 25, 29.97, 50, 59.94), aborting." | |
exit | |
fi | |
fi | |
IFS="$OIFS" | |
echo "---> [$counter] input:$file output:${file%.*}$suffix.mov" | |
echo "---> [$counter] resolution: $size, fps: $framerate, bitrate: $bitrate, codec: $codec" | |
ffmpeg -i $file ${options} "$TRANSCODED_DIR/${file%.*}$suffix.mov" | |
# following command copies CreateDate tag to FileModifyDate because it seems Resolve looks | |
# at this tag as the equivalent for creation date | |
exiftool "-FileModifyDate<CreateDate" -overwrite_original -progress "$TRANSCODED_DIR/${file%.*}$suffix.mov" | |
IFS=$'\n' | |
mv "$file" -t $ORIGINAL_DIR | |
done | |
done | |
IFS="$OIFS" | |
current_time=$(date +"%Y/%m/%d %H:%M:%S") | |
echo "---> END $current_time" | |
#------------------------------------------------------------------------------------- | |
# DNxHD, DNxHR references: | |
# | |
# https://askubuntu.com/questions/907398/how-to-convert-a-video-with-ffmpeg-into-the-dnxhd-dnxhr-format | |
# http://avid.force.com/pkb/articles/en_US/White_Paper/DNxHR-Codec-Bandwidth-Specifications | |
# | |
# | Frame size | Bitrate | Pixel Format | FPS | | |
# | ---------- | ------- | ------------ | ----------------| | |
# |*1920x1080p | 36Mbps | yuv422p | 24 (24000/1001) | | |
# | 1920x1080p | 115Mbps | yuv422p | 24 (24000/1001) | | |
# | 1920x1080p | 175Mbps | yuv422p | 24 (24000/1001) | | |
# |*1920x1080p | 36Mbps | yuv422p | 25 | | |
# | 1920x1080p | 120Mbps | yuv422p | 25 | | |
# | 1920x1080p | 185Mbps | yuv422p | 25 | | |
# | 1920x1080p | 45Mbps | yuv422p | 30 (30000/1001) | | |
# |*1920x1080p | 145Mbps | yuv422p | 30 (30000/1001) | | |
# | 1920x1080p | 220Mbps | yuv422p | 30 (30000/1001) | | |
# |*1920x1080p | 75Mbps | yuv422p | 50 | | |
# | 1920x1080p | 240Mbps | yuv422p | 50 | | |
# | 1920x1080p | 365Mbps | yuv422p | 50 | | |
# |*1920x1080p | 90Mbps | yuv422p | 60 (60000/1001) | | |
# | 1920x1080p | 290Mbps | yuv422p | 60 (60000/1001) | | |
# | 1920x1080p | 440Mbps | yuv422p | 60 (60000/1001) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment