Skip to content

Instantly share code, notes, and snippets.

@aadm
Created November 16, 2020 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aadm/1910d06a749412a0b90db51d120ffa70 to your computer and use it in GitHub Desktop.
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.
#!/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