M: I need a quick ffmpeg script to split at a given list of time codes an MP4without re-encoding
G: You can use the
ffmpeg command with the -c copy option to
split an MP4 file at specified timecodes without re-encoding. Here's a
simple script:
#!/bin/bash
# Input video file
input_file="input.mp4"
# Timecodes (start and end times in seconds)
# Format: "start1:end1 start2:end2 ..."
timecodes=("0:10" "10:20" "20:30")
# Output prefix
output_prefix="output"
# Loop through timecodes and split the file
counter=1
for tc in "${timecodes[@]}"; do
start_time=$(echo $tc | cut -d':' -f1)
end_time=$(echo $tc | cut -d':' -f2)
ffmpeg -i "$input_file" -ss "$start_time" -to "$end_time" -c copy "${output_prefix}_part${counter}.mp4"
((counter++))
done
echo "Splitting complete."input.mp4 with your file name.timecodes array with your desired start and
end times.output_part1.mp4, output_part2.mp4, etc.M: This bash line: elif (( $(echo “$FRAME_RATE > 30” | bc -l) || ( $recodeFile -eq 1 ) )); then Is giving me grief and considers ‘recodeFile’ to be a function name. … any clue what‘s going on?
G: The issue is likely related to
how the shell interprets recodeFile as a function rather
than a variable. This happens because in bash, unquoted
variables or incorrect syntax can confuse the interpreter. Here's a
breakdown and solution:
$recodeFile is unquoted, it might be misinterpreted in the
context of the command.echo: Smart
quotes (“”) in echo "$FRAME_RATE > 30" can
cause syntax errors.bc or Condition Syntax:
Logical operators (||) inside (( )) can be
problematic when mixing arithmetic and command substitutions.Here’s how you can fix the line:
elif (( $(echo "$FRAME_RATE > 30" | bc -l) || recodeFile == 1 )); then"") instead of smart quotes (“”).recodeFile is
treated as a variable. In bash, == is used for
numeric equality in logical checks inside (( )).||) are better handled outside command substitutions.If bc is still causing issues, you can split the
logic:
is_frame_rate_high=$(echo "$FRAME_RATE > 30" | bc -l)
if (( is_frame_rate_high == 1 || recodeFile == 1 )); then
# Your code here
fiThis separates the floating-point comparison from the main logic, making it clearer.
M: an if statement to compare variable x to string “y”
G: In bash, you can
compare a variable x to a string "y" using the
[ ] or [[ ]] syntax. Here's an example:
if [ "$x" == "y" ]; then
echo "x is equal to y"
else
echo "x is not equal to y"
fi"$x"), especially if they might be empty or contain
spaces, to avoid syntax errors.[ "$x" = "y" ]: Works in both POSIX sh and
bash.[ "$x" == "y" ]: bash-specific, but
commonly used.[[ ]] (Preferred
in Bash):if [[ "$x" == "y" ]]; then
echo "x is equal to y"
else
echo "x is not equal to y"
fiThe [[ ]] syntax is more robust for string comparisons
and allows advanced features like pattern matching
(== "*pattern*").
M: Could I build a command with options based on if then statements, then execute the command
G: Yes, you can build a command
dynamically using variables and conditionals, and then execute it in
bash. Here's an example of how to achieve this:
#!/bin/bash
# Initialize the command
cmd="ffmpeg"
# Add options conditionally
if [ "$option1" == "true" ]; then
cmd+=" -option1 value1"
fi
if [ "$option2" == "true" ]; then
cmd+=" -option2 value2"
fi
if [ "$file" != "" ]; then
cmd+=" -i $file"
fi
# Set output file
cmd+=" output.mp4"
# Print the final command for debugging (optional)
echo "Executing: $cmd"
# Execute the command
eval $cmdBuilding the Command:
cmd="ffmpeg").cmd+=" ...". The
+= operator appends to the string.Execute the Command:
eval $cmd to execute the dynamically built
command.Debugging:
echo "Executing: $cmd") helps you
verify it before execution.If option1=true, option2=false, and
file="input.mp4", the script generates and executes:
ffmpeg -option1 value1 -i input.mp4 output.mp4M: Will that evaluation include variables that have been set?
G: Yes, the eval $cmd
approach will include all variables that were dynamically set during the
script. When you append or construct the cmd string using
variables (e.g., cmd+=" -i $file"), the variable values are
expanded at runtime as the command is constructed.
#!/bin/bash
# Example variables
file="input.mp4"
option1="true"
option2="false"
bitrate="500k"
# Build the command
cmd="ffmpeg"
if [ "$option1" == "true" ]; then
cmd+=" -b:v $bitrate" # Add bitrate option
fi
if [ "$option2" == "true" ]; then
cmd+=" -preset fast"
fi
cmd+=" -i $file output.mp4"
# Print for debugging
echo "Command: $cmd"
# Execute the command
eval $cmdVariable Expansion:
$file is expanded into "input.mp4".$bitrate is expanded into "500k".Debugging:
echo "Command: $cmd" outputs the full, constructed
command so you can confirm it’s correct.Execution:
eval $cmd runs the full command, with all variables
resolved.If the variables are set as above, the script will:
Command: ffmpeg -b:v 500k -i input.mp4 output.mp4ffmpeg -b:v 500k -i input.mp4 output.mp4cmd+=" -i \"$file\"").eval if any variables are
user-provided, as it could execute unintended commands (potential
security risk).