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."

How to Use:

  1. Replace input.mp4 with your file name.
  2. Modify the timecodes array with your desired start and end times.
  3. Run the script. Each split part will be saved as 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:

Possible Issues:

  1. Variable Not Properly Quoted: If $recodeFile is unquoted, it might be misinterpreted in the context of the command.
  2. Use of Double Quotes for echo: Smart quotes (“”) in echo "$FRAME_RATE > 30" can cause syntax errors.
  3. Improper bc or Condition Syntax: Logical operators (||) inside (( )) can be problematic when mixing arithmetic and command substitutions.

Corrected Code:

Here’s how you can fix the line:

elif (( $(echo "$FRAME_RATE > 30" | bc -l) || recodeFile == 1 )); then

Key Fixes:

  1. Proper Quotes: Use straight quotes ("") instead of smart quotes (“”).
  2. Variable Check: Ensure recodeFile is treated as a variable. In bash, == is used for numeric equality in logical checks inside (( )).
  3. Simplify Arithmetic Checks: Logical operations (||) are better handled outside command substitutions.

Alternative if the Above Fails:

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
fi

This 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

Key Notes:

  1. Use Quotes: Always quote your variables ("$x"), especially if they might be empty or contain spaces, to avoid syntax errors.
  2. String Comparison Operators:

Using [[ ]] (Preferred in Bash):

if [[ "$x" == "y" ]]; then
  echo "x is equal to y"
else
  echo "x is not equal to y"
fi

The [[ ]] 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 $cmd

Explanation:

  1. Building the Command:

  2. Execute the Command:

  3. Debugging:

Example Run:

If option1=true, option2=false, and file="input.mp4", the script generates and executes:

ffmpeg -option1 value1 -i input.mp4 output.mp4

M: 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.

Example with Variables:

#!/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 $cmd

Breakdown:

  1. Variable Expansion:

    • $file is expanded into "input.mp4".
    • $bitrate is expanded into "500k".
  2. Debugging:

    • echo "Command: $cmd" outputs the full, constructed command so you can confirm it’s correct.
  3. Execution:

    • eval $cmd runs the full command, with all variables resolved.

Example Output:

If the variables are set as above, the script will:

  1. Print:
    Command: ffmpeg -b:v 500k -i input.mp4 output.mp4
  2. Execute:
    ffmpeg -b:v 500k -i input.mp4 output.mp4

Important Notes: