A great programme, an add-on to Resolve, allowing you to create proxy files in the background without involving the main programme. However, its rather significant limitation is the rigid rule for creating proxy directories. They are always placed in the directory containing video files. So we always have a structure like this:
/rootDir
-> /videoDir
-> /Proxy
Which is actually quite logical, but life has its dark sides. Firstly, we may not want to have a proxy on that drive, and secondly, there is simply no space on it. This was the case for me. The raw material, i.e. the source files, were on an external SSD drive, quite large at 2TB, but filled to the brim. There was maybe 50MB left. About 1,400 files for a nature film. In a dozen or so different formats and resolutions. Nothing unusual, they came from various cameras, some from phones. And since I couldn't copy them to another, larger drive to make room for the proxies, I looked for a solution. Anyway, copying them just to create proxies didn't make sense to me.
But back to Blackmagic Proxy Generator, the second thing that is a bit annoying, at least for me, is the selection of codecs in which you can create the target proxies. Unfortunately, there are only a few to choose from, perhaps logical, but not everyone may find this selection suitable. That's the short story of how the idea for my own solution came about.
An additional argument was the fact that generating proxy files with DaVinci Resolve itself allows you to specify the destination, but then blocks the programme. And cherry on top was the fact that DaVinci simply crashed several times during generation.
In the first phase, I simply came up with a logical solution: creating symlinks. In short, these are symbolic links from one directory to another (for those unfamiliar with the concept, they are like ‘shortcuts’ to files).
First, I wrote a script that intercepted the generator's requests to create a proxy directory, captured the request, and created a symlink ‘on the fly’. It seemed to work, but then again, it didn't. Sometimes the generator was faster than the script and saved the first proxy file according to its algorithm, sometimes it managed to intercept and link correctly. So that wasn't the way to go. Anyway, what's the point of intercepting directory creation requests when I know what will be needed? So the next step was to simply create predefined symlinks and target directories, consistent with the structure expected by DaVinci Resolve.
Ultimately, to cut a long story short, a script was created that recursively went through the source file directory/drive, creating directories with the names of the current directory in the destination, and creating a symlink called ‘proxy’ in the source directory, pointing to that directory. It's a bit complicated, but I couldn't explain it any easier.
Let's go through how it works step by step:
and so on until all directories are exhausted. So, in the destination, we have, in fact, mirror copies of the directories from the source drive, but DaVinci Resolve or Blackmagic Proxy Generator sees them as the correct proxy directory structure. It would be possible to create directories with the original names on the destination drive/directory, and only then create proxy directories within them. But why? That would be art for art's sake.
One drawback should be noted: the script searches everywhere, so in the case of the XDCAM structure, where files are located in the /XDROOT/Clip subdirectory, it will create a symlink to the Clip directory. The same applies to the even more idiotic BPAV structure, where each video file has its own separate directory. It is best to simply move the video files to the appropriate/parent/own directory. There is no point in explaining this here; anyone who has encountered these file formats knows what this is about.
Here is the content of the script for creating a proxy structure for Resolv, which I finally came up with after several attempts (I almost deleted the source files, but I have a backup, which I recommend everyone to do).
I even added something like a help section, which I don't normally do, and after a few months I'm wondering how the hell it was used :) Just copy the text content to a file, for example proxyCreator.sh, save it somewhere on your hard drive, give it executable rights and just use it. Of course, it's not a programme with a stunningly beautiful graphical interface, but a script to run in the console or terminal. It may not be perfect, like nothing else on this planet, but it works very well for me. And if something doesn't work for you, you can always improve it.
A small note: if you want to use Bash, make sure you have at least version 4.1, otherwise it will crash when writing logs. Unfortunately, due to the type of Bash licence, Apple uses version 3.2.57 even in its latest machines. This is supposedly because Bash version 4.0 and above is licensed under GPL v3, which Apple somehow does not like. Why? Who knows. When you don't know what's going on, it's probably about money :-) It's a bit of a shame, but on the other hand, Zsh is very compatible with Bash, and practically everything works without any problems. And certainly simple scripts like this one for creating proxy directories.
#!/bin/zsh
# --- help ---
usage() {
cat << EOF
Use: $0 [OPTION] SRC DST
Creates a directory structure on the DST, and proxy symlinks in the source directories
that point to these directories. Used to bypass BlackmagicProxyGenerator restrictions, where it is
not possible to specify the destination directory, which can be problematic in the case of a full source drive.
Thanks to this approach, you do not take up space on your source drive,
and all proxy directories point to your destination on another drive. And DaVinci Resolve works flawlessly.
--
The script is designed for Mac OSX or Linux. It may be possible to adapt it for Windows, but I am not familiar with that.
The script may contain errors. Use it at your own risk. If you notice any irregularities,
please let me know and I will correct them in my spare time. Enjoy using it, martvin.
admin @ projektika.group
OPION:
--clean Removes existing directories or proxy symlinks before creating new ones.
--exec Makes actual changes (default: dry-run mode)
--log [FILE] Saves the activity log. If FILE is not specified, a file with the date is created.
--help This page
EXAMPLE:
$0 /Volumes/SRC /Volumes/DST
$0 --exec /Volumes/SRC /Volumes/DST
$0 --clean --exec --log SRC DST
$0 --exec --log /path/to/my_proxy.log SRC DST
ATTENTION:
- Dry-run mode is the default for safety.
- Symlinks are only created if they do not exist (unless --clean is used).
- Source directories are not modified except for the proxy directory.
EOF
exit 1
}
# --- default settings ---
CLEAN=0
EXEC=0
DRY_RUN=1
LOG_FILE=""
# --- args parse ---
while [[ $# -gt 0 ]]; do
case $1 in
--clean)
CLEAN=1
shift
;;
--exec)
EXEC=1
DRY_RUN=0
shift
;;
--log)
if [[ -n "$2" && ! "$2" =~ ^--.* ]]; then
potential_path="$2"
shift 2
else
potential_path="proxy_log_$(date %Y%m%d-%H%M%S).log"
shift
fi
potential_path="${potential_path%/}"
if [[ -d "$potential_path" ]]; then
# if directory, create log file inside it
LOG_FILE="$potential_path/proxy_log_$(date %Y%m%d-%H%M%S).log"
elif [[ -n "$potential_path" ]]; then
# if file path, check if directory exists
log_dir="$(dirname "$potential_path")"
if [[ -d "$log_dir" ]]; then
LOG_FILE="$potential_path"
else
echo -e "\033[1;31mError: dir not exist: $log_dir\033[0m"
exit 1
fi
else
echo -e "\033[1;31mError: wrong path after --log\033[0m"
exit 1
fi
;;
--help)
usage
;;
*)
if [[ -z "$SRC" ]]; then
SRC="$1"
elif [[ -z "$DST" ]]; then
DST="$1"
else
echo "Error: Too many arguments."
usage
fi
shift
;;
esac
done
# --- Checking required arguments ---
if [[ -z "$SRC" || -z "$DST" ]]; then
echo "\033[1;31mError: The required SRC or DST arguments are missing, or the --log option was used without a path to the log directory.\033[0m"
usage
fi
# --- path validate ---
if [[ ! -d "$SRC" ]]; then
echo "Error: Source directory does not exist: $SRC"
exit 1
fi
# --- logs ---
LOG_FD=1 # default stdout
if [[ -n "$LOG_FILE" ]]; then
# dir exists
log_dir=$(dirname "$LOG_FILE")
if [[ ! -d "$log_dir" ]]; then
echo "Error: Log directory not exist: $log_dir"
exit 1
fi
# log file
exec {LOG_FD}>>"$LOG_FILE"
echo "=== Log start: $(date) ===" >&$LOG_FD
echo "Mode: $( [[ $DRY_RUN -eq 1 ]] && echo dry-run || echo exec )"
echo "SRC: $SRC"
echo "DST: $DST"
echo "Args: $( [[ $CLEAN -eq 1 ]] && echo '--clean ' || echo '')$( [[ $EXEC -eq 1 ]] && echo '--exec ' || echo '')$( [[ -n "$LOG_FILE" ]] && echo "--log $LOG_FILE" || echo '')"
echo "---" >&$LOG_FD
fi
# --- function ---
log_action() {
local msg="$1"
# terminal
if [[ $DRY_RUN -eq 1 ]]; then
echo "[DRY RUN] $msg"
else
echo "$msg"
fi
# file
if [[ -n "$LOG_FILE" ]]; then
local prefix=$( [[ $DRY_RUN -eq 1 ]] && echo "[DRY RUN]" || echo "[EXEC]" )
echo "$prefix $msg" >&$LOG_FD
fi
}
run() {
if [[ $DRY_RUN -eq 1 ]]; then
echo "[DRY RUN] $*" | tee -a /dev/fd/$LOG_FD 2>/dev/null
else
echo "[EXEC] $*" >&$LOG_FD
"$@"
fi
}
# --- main exec ---
if [[ $EXEC -eq 1 && ! -d "$DST" ]]; then
echo "[EXEC] Creating a target directory: $DST"
mkdir -p "$DST" || { echo "Error: Cannot create $DST"; exit 1; }
elif [[ $DRY_RUN -eq 1 && ! -d "$DST" ]]; then
log_action "Target directory required: $DST (will be created with --exec)"
fi
while IFS= read -r -d '' dir; do
# skip proxy exist dir
if [[ $(basename "$dir") == "proxy" ]]; then
continue
fi
# check for video file in dir
if find "$dir" -maxdepth 1 -type f \( \
-iname "*.mov" -o \
-iname "*.mp4" -o \
-iname "*.mxf" \
\) | grep -q .; then
rel_path="${dir#$SRC/}"
[[ "$rel_path" == "$dir" ]] && rel_path="" # ending /
target_dir="$DST/$rel_path"
proxy_path="$dir/proxy"
# 1. Create the target directory
run mkdir -p "$target_dir"
log_action "Make proxy dir: $target_dir"
# 2. Delete existing symlink/directory ONLY if --clean
if [[ $CLEAN -eq 1 ]]; then
if [[ -d "$proxy_path" || -L "$proxy_path" ]]; then
run rm -rf "$proxy_path"
log_action "The existing symlink/directory has been removed: $proxy_path"
fi
fi
# 3. Create a symlink only if not exist
if [[ -L "$proxy_path" ]]; then
current_target=$(readlink "$proxy_path" 2>/dev/null || echo "???")
if [[ "$current_target" == "$target_dir" ]]; then
log_action "Skip, symlink exitst: $proxy_path → $current_target"
else
log_action "Skip, symlink exists, but it points to: $proxy_path → $current_target"
fi
else
run ln -s "$target_dir" "$proxy_path"
log_action "Symlink sreate: $proxy_path → $target_dir"
fi
fi
done < <(find "$SRC" -type d -print0)
# --- close log ---
if [[ -n "$LOG_FILE" ]]; then
echo "=== End: $(date) ===" >&$LOG_FD
exec {LOG_FD}<&- # close file
echo "Log saved to: $LOG_FILE"
fi
echo ""
if [[ $DRY_RUN -eq 1 ]]; then
echo "Dry-run mode completed. No changes were made."
echo "Use --exec to make changes."
else
if [[ $CLEAN -eq 1 ]]; then
echo "Done. Proxies have been refreshed. (--clean)."
else
echo "Done. New proxy links have been added (incremental mode)."
fi
fi
And that's how we create directories in any location where proxy files will be generated. This is when using Blackmagic Proxy Generator. As mentioned earlier, Resolve DaVinci itself has the ability to specify where they should be located. Additionally, when we need to transfer proxy files, for example to a laptop, so that we don't waste time on the beach during our holiday :-), we simply copy the directory and we have a copy of the original. There is no need to do any extract proxy or anything like that.
I recommend using the --log option. You can specify a path with your own file name or just indicate the destination directory for the log.
So if we use the syntax proxyCreator.sh --log DestinationDir SourceDir DestinationDir, we will get logs in the destination directory, named ‘proxy_log_Current-Date-Hour-Minute.log’. After a few weeks or months, this information may prove to be quite useful. And when running without the --exec option, we get a simulation of future actions, so we can track what will be done. This can be useful when there are a large number of proxy directories, because it may turn out that some of the directories have their own symlinks generated.
But since we said A, we had to say B, so the next step was to create our own generator of proper video proxy files, with any codec, size or bitrate. In other words, a technological race with Blackmagic :-)
So, let's keep going. We already have a lovely proxy directory structure, now it's time to fill it with some files. The simplest solution for processing all kinds of video files from the console is FFMPEG. It's an inconspicuous little programme, but it can do pretty much everything. Well, except for cooking and cleaning the house.
It has many variants and modifications, but personally, I just use the classic installation via brew install ffmpeg. Maybe other versions sometimes have more features, but I need simple solutions. Yes, for example, FFMBC is designed for professional video processing, but I only create proxies :-)
Let's get back to generating files. This time, I gave up ‘Zsh’ in favour of plain ‘Bash’. Quite simply, I already had a simple version of the script from years ago, and I wasn't going to rewrite it to a supposedly compatible, but not entirely compatible, format. The details are not important, but passing arguments as arrays or as strings does make a difference. Or maybe I just don't know anything about it. Let's not get into it, and I'm not going to start a flame war about which is better. Sometimes something is useful or ready, and sometimes something else is.
So, based on an old, few-line script, something like a ‘combine harvester’ for proxy files was created. Originally, there was an idea to combine proxyDirCreator and proxyFileGenerator (I gave the files such proud names :-), but that would have been totally pointless. Not everyone needs to symlink proxy directories to another drive.
So, the script recursively searches the source directory, looks for .mov, .mp4, and .mxf files (the ones I encounter most often at work), and if it does not exist, it creates a proxy directory at the given level (if it exists, it uses the existing one, whether it is a directory or a symlink), compresses all files from the given directory, adds the result to a ‘.csv’ file as a kind of log, and continues its journey through the directories. And so it wanders until it has processed all the files in a given location.
It has several options, all of which are included in the script code, so there is no point in discussing them here. In any case, as with proxyDirCreator, it does not create anything by default, but only shows what it would like to do. It is always better to see in advance what kind of changes a programme is going to make than to cry later that something has gone wrong.
If you want to generate several files at once, you need to install GNU Parallel. To be honest, I don't know how many cores FFMpeg uses during operation, but I have a feeling it's only one. So multiplying the number of processes can significantly reduce the generation time, and you can still work on the other cores. But that's a topic for a separate article. In any case, it works for me, and it's pretty fast. However, I use an Apple M4 processor, which is quite fast in itself. I didn't have a chance to test it on other machines.
#!/bin/bash
# --- help ---
usage() {
cat << EOF
Usage: $0 [quality] [--jobs N] [--overwrite] [--exec]
Example: $0 /Users/user/Projekt medium # simulation mode, default
$0 /Users/user/Projekt medium --exec # single mode
$0 /Users/user/Projekt medium --jobs 4 --overwrite --exec # parallel mode, overwrite old proxy
Generates proxy files with the selected quality setting. Works recursively, skips "proxy" directories.
---
The script is designed for Mac OSX or Linux. It may be possible to adapt it for Windows, but I am not familiar with that.
The script may contain errors. Use it at your own risk. If you notice any irregularities,
please let me know and I will correct them in my spare time. Enjoy using it :-)
martvin
admin @ projektika.group
---
ARGUMENTS:
start_path Directory to start searching from
quality Quality profile (default: medium, see options below)
light - low bitrate, fast, half resolution (H.264)
medium - speed/quality balance, half resolution (H.264)
high - full resolution, high quality (H.264)
h265-half - half resolution, excellent compression (H.265/HEVC)
h265-full - full resolution, excellent compression (H.265/HEVC)
prores - ProRes 422 (10-bit), half resolution
prores-lt - ProRes LT (lower bitrate), half resolution
prores-proxy - ProRes Proxy (dedicated proxy codec), half resolution
prores-proxy-full - ProRes Proxy, full resolution
OPTIONS:
--jobs N Number of parallel processes (default: 1), use with GNU parallel
--overwrite Overwrite existing proxy files
--exec Execute (without this flag runs in dry-run mode)
--dry-run Shows what it would do without generating (default)
EOF
exit 1
}
if [ $# -eq 0 ]; then
echo "Please specify the start path"
usage
fi
# --- dependency check ---
check_dependencies() {
if ! command -v ffmpeg &> /dev/null; then
echo "\033[1;31mERROR: ffmpeg is not installed or not in PATH.\033[0m"
echo "\033[1;31minstall: brew install ffmpeg\033[0m"
exit 1
fi
if [[ $jobs -gt 1 ]] && ! command -v parallel &> /dev/null; then
echo "\033[1;31mWARNING: GNU parallel is not installed - working sequentially.\033[0m"
jobs=1
fi
}
start_path="$1"
quality="${2:-medium}"
jobs=1
overwrite=0
DRY_RUN=1
# Parsing additional arguments
shift 2 # skip after start_path & quality
while [[ $# -gt 0 ]]; do
case "$1" in
--jobs)
if [[ -n "$2" && "$2" =~ ^[0-9] $ ]]; then
jobs="$2"
shift 2
else
echo "\033[1;31mERROR: --jobs needs a number.\033[0m"
usage
fi
;;
--overwrite)
overwrite=1
shift
;;
--exec)
DRY_RUN=0
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--help)
usage
;;
*)
echo "Unknown option: $1, maybe a typo? Use --help for help."
shift
;;
esac
done
# Validate start path
if [ ! -d "$start_path" ]; then
echo "\033[1;31mERROR: Directory '$start_path' does not exist\033[0m"
exit 1
fi
case "$quality" in
light)
scale="scale=iw/2:ih/2"
codec="-c:v libx264 -preset ultrafast -crf 28 -pix_fmt yuv420p -c:a aac -b:a 128k"
ext="mp4"
;;
medium)
scale="scale=iw/2:ih/2"
codec="-c:v libx264 -preset fast -crf 23 -pix_fmt yuv420p -c:a aac -b:a 192k"
ext="mp4"
;;
high)
scale="scale=iw:ih"
codec="-c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p -c:a aac -b:a 256k"
ext="mp4"
;;
h265-half)
#compatible setting for macosx quicktime player - -profile:v main -level 4.0 -tag:v hvc1
scale="scale=iw/2:ih/2"
codec="-c:v libx265 -preset medium -crf 26 -pix_fmt yuv420p -profile:v main -level 4.0 -tag:v hvc1 -c:a aac -b:a 192k"
ext="mp4"
;;
h265-full)
#compatible setting for macosx quicktime player
scale="scale=iw:ih"
codec="-c:v libx265 -preset medium -crf 23 -pix_fmt yuv420p -profile:v main -level 4.0 -tag:v hvc1 -c:a aac -b:a 256k"
ext="mp4"
;;
prores)
#prores halfres normal codec
scale="scale=iw/2:ih/2"
codec="-c:v prores_ks -profile:v 2 -pix_fmt yuv422p10le -vendor apl0 -bits_per_mb 2000 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -c:a pcm_s16le"
ext="mov"
;;
prores-lt)
scale="scale=iw/2:ih/2"
codec="-c:v prores_ks -profile:v 1 -pix_fmt yuv422p10le -vendor apl0 -bits_per_mb 3500 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -c:a pcm_s16le"
ext="mov"
;;
prores-proxy)
scale="scale=iw/2:ih/2"
codec="-c:v prores_ks -profile:v 0 -pix_fmt yuv422p10le -vendor apl0 -bits_per_mb 2000 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -c:a pcm_s16le"
ext="mov"
;;
prores-proxy-full)
scale="scale=iw:ih"
codec="-c:v prores_ks -profile:v 0 -pix_fmt yuv422p10le -vendor apl0 -bits_per_mb 2000 -colorspace bt709 -color_primaries bt709 -color_trc bt709 -c:a pcm_s16le"
ext="mov"
;;
*)
echo "Error in quality settings: $quality"
echo "Available options: light|medium|high|h265-half|h265-full|prores|prores-lt|prores-proxy|prores-proxy-full"
exit 1
;;
esac
# Generate CSV filename with timestamp and quality
timestamp=$(date "%Y%m%d_%H%M%S")
csv_file="$start_path/proxy_log_${timestamp}_${quality}.csv"
# old maps, when DJI file, generate bad TC. Simply put, these "idiots" do not adhere to any standards.
# maps="-map 0:v:0 -map 0:a? -map_metadata 0 -copytb 1"
#new maps, i hope is ok :-)
maps="-map 0:v:0 -map 0:a? -map_metadata 0"
check_dependencies
# Create CSV header
echo -e "origin_file\tproxy_file\tcreation_time\tduration" > "$csv_file"
create_proxy() {
local file="$1"
local dir_name=$(dirname "$file")
local basename=$(basename "$file")
local filename="${basename%.*}"
local output_dir="$dir_name/Proxy"
local output_file="$output_dir/$filename.$ext"
# Check if ffmpeg is available
local ffPath=$(command -v ffmpeg)
if [ -z "$ffPath" ]; then
echo "ERROR: ffmpeg not found in PATH"
return 1
fi
mkdir -p "$output_dir"
# Check if a file with the same name but different extension already exists
local mp4_file="$output_dir/$filename.mp4"
local mov_file="$output_dir/$filename.mov"
# Check file existence if not overwrite
if [ "$overwrite" -eq 0 ]; then
if [ -f "$mp4_file" ] || [ -f "$mov_file" ]; then
echo "File exists (as .mp4 or .mov), skipping: $output_file"
return 0
fi
fi
# Set ffmpeg overwrite flag
local ffmpeg_flag=""
if [ "$overwrite" -eq 1 ]; then
ffmpeg_flag="-y"
else
ffmpeg_flag="-n"
fi
# check if attached pic
attached_id=$(ffmpeg -hide_banner -i "$file" 2>&1 | grep "Video.*attached pic" | sed -E 's/.*Stream #0:([0-9] )\[.*:([0-9] )\].*/\2/' | head -n1)
# new maps
if [ -n "$attached_id" ]; then
echo "Attached picture detected on stream #$attached_id — excluding it..."
map_fix="$maps -map -0:v:$attached_id"
else
map_fix="$maps"
fi
if [ $DRY_RUN -eq 1 ]; then
echo "[DRY RUN] Would run: $ffPath -nostdin $ffmpeg_flag -i \"$file\" $map_fix -vf \"$scale\" $codec \"$output_file\""
return 0
fi
# Execute ffmpeg
echo "Processing: $file → $output_file"
if ! < /dev/null $ffPath -nostdin $ffmpeg_flag -i "$file" $map_fix \
-vf "$scale" \
$codec \
"$output_file" 2> >(tee "/tmp/ffmpeg_error.log" >&2); then
echo "ERROR: Failed to process $file"
echo " See detailed log: /tmp/ffmpeg_error.log"
tail -n 20 /tmp/ffmpeg_error.log
echo ""
return 1
fi
# Extract metadata
local ffmpeg_metadata=$($ffPath -i "$file" 2>&1)
local duration=$(echo "$ffmpeg_metadata" | grep "Duration:" | head -n 1 | awk '{print $2}' | sed 's/,//')
local creation_time=$(echo "$ffmpeg_metadata" | grep -i "creation_time" | head -n 1 | awk '{print $3" "$4}')
# Write to CSV
echo -e "$file\t$output_file\t$creation_time\t$duration" >> "$csv_file"
echo "Finished: $file → $output_file"
return 0
}
# Export function and variables for parallel processing
export -f create_proxy
export scale codec ext csv_file overwrite DRY_RUN maps
# Display settings
echo "=== Proxy Generator Settings ==="
echo "Start path: $start_path"
echo "Quality: $quality"
echo "Jobs: $jobs"
echo "Overwrite: $([ $overwrite -eq 1 ] && echo "yes" || echo "no")"
echo "Mode: $([ $DRY_RUN -eq 1 ] && echo "DRY RUN" || echo "EXECUTION")"
echo "CSV output: $csv_file"
echo "================================"
# Main processing
if [ "$jobs" -gt 1 ]; then
if command -v parallel > /dev/null 2>&1; then
echo "Starting parallel processing with $jobs jobs..."
find "$start_path" -type f \( -iname "*.mxf" -o -iname "*.mp4" -o -iname "*.mov" \) \
-not -path "*/proxy" -not -path "*/proxy/*" -print0 | \
parallel -0 -j"$jobs" create_proxy
else
echo "WARNING: GNU parallel is not installed. Falling back to sequential mode..."
jobs=1
fi
fi
if [ "$jobs" -eq 1 ]; then
echo "Starting sequential processing..."
while IFS= read -r -d '' file; do
create_proxy "$file"
done < <(find "$start_path" -type f \( -iname "*.mxf" -o -iname "*.mp4" -o -iname "*.mov" \) \
-not -path "*/Proxy" -not -path "*/Proxy/*" -print0)
fi
echo "Processing completed. Results saved to: $csv_file" Of course, the script can be expanded. For example, it would be useful to be able to simply generate a proxy from A to B, without creating symlinks or directories. But I just wanted to simulate the operation of the original program. The possibilities are endless, and each user probably has different needs. Well, nobody's perfect :-)
The second thing to clarify is that the arguments in one script are at the beginning, while in the other they are at the end of the command. Well, it just stayed that way from the previous version. It didn't even occur to me to correct it to make it the same. But there were those who noticed :-) Thanks for the comments, but this is basically no obstacle to use. In addition, every change helps us break the routine a little, which means our brain works more efficiently :-)
After a brief adventure with ComfyUI (unfortunately, due to my own carelessness, I ran it in a non-isolated environment), it deleted ffmpeg. Oh well, trusting the console, I run ‘brew install ...’, and then some dependency doesn't have the right SSL certificate, or who knows what went wrong. After a moment's thought, I came to the conclusion that yes, brew is convenient, but I don't really need it. I only need FFMpeg and FFProbe. And since the evermeet.cx website offers ready-made binaries (in my case for mac osx) for both of these programmes, it will be easiest to just use the ready-made ones instead of building the entire dependency tree. It may be a bit confusing, like all my descriptions, but I simply do not need advanced codecs for ordinary proxy creation. And the ones included in the binary versions of FFMpeg are more than enough.
Let's not prolong this, here is a ready-made script that installs FFMpeg and FFProbe in the latest available version, without Homebrew, compilation, or other strange things :-)
#!/bin/bash
set -e
# install binary without Homebrew
install_binary() {
local name=$1
local tmpfile="/tmp/${name}.zip"
local url="https://evermeet.cx/ffmpeg/getrelease/${name}/zip"
echo "|-> Get ${name}..."
curl -L "$url" -o "$tmpfile" || {
echo -e "\033[0;31m Failed to download ${name}.\033[0m"
return 1
}
echo "Unpack ${name}..."
unzip -o "$tmpfile" -d /tmp/
echo "|-> Install ${name} to /usr/local/bin..."
sudo mv "/tmp/${name}" "/usr/local/bin/${name}"
sudo chmod x "/usr/local/bin/${name}"
echo "|-> Clear... "
rm -f "$tmpfile"
echo "|-> ${name} updated!"
"/usr/local/bin/${name}" -version | head -n 1
echo
}
echo "==============================="
echo "Install/update FFmpeg & FFprobe"
echo "==============================="
install_binary ffmpeg
install_binary ffprobe
echo -e "\033[0;32m All OK! \033[0m"
Just copy, paste into a file, give it execute permissions and run it in the console. It will probably ask for a password before installing FFMpeg, but it varies. And as they say, ‘Everything works for me’ :-)
Removed the track with ‘attached pic’, which sometimes caused strange behaviour, especially with DJI files. And in those same files, there was a bigger problem with timecodes. Osmo DJI supposedly has a TC track, but it is marked as ‘codec:none’. DJI drones do not have TC at all, at most a timestamp in the name or header. Theoretically, the ‘-map 0:d?’ option should ignore the lack of a track, but it does not quite work.
This is the case, for example, with the `codec:none` marking, which is a total mistake in my opinion. But that's just my personal opinion, it probably has some hidden meaning.
In any case, if you absolutely need a TC track, and generally timecode is almost always saved as metadata, add ‘-map 0:d?’ to the maps declaration. That's it. You could expand it, add exceptions, some if and else statements. But universality has its limits. So does my patience :-)