フォルダ内のmp4ファイルをつなげてSDフォーマットで保存する

# はじめに

講義を手持ちのビデオカメラで撮影すると、1.3GBごとにMP4ファイルが作られ、後で手動で結合しないといけない。この作業を自動化するため、concat_mp4という命令を作ってzshから動かせるようにした。コード自体はClaude3.7で生成してデバッグを行った。

# zsh シェルスクリプト

ファイル名をconcat_mp4.zshとした。

```zsh
#!/bin/zsh

echo "=== MP4 Concatenation Script ==="
echo "Starting concatenation process..."

# Create a temporary file to store the list of files
temp_file="temp_file_list.txt"
echo "Creating temporary file: $temp_file"

# Clear the temporary file if it exists - using rm first then touch instead of redirection
if [[ -f "$temp_file" ]]; then
  rm -f "$temp_file"
fi
touch "$temp_file"
echo "Cleared/created temporary file."

echo "Scanning for MP4 files in current directory..."

# Check for both .mp4 and .MP4 files
mp4_files=(*.[mM][pP]4)
if [[ ! -f "${mp4_files[1]}" ]] || [[ "${mp4_files[1]}" == "*.[mM][pP]4" ]]; then
  echo "No MP4 files found in directory."
else
  echo "Found ${#mp4_files[@]} potential MP4 files."
  # Find all MP4 files in the current directory and add them to the file list
  for file in "${mp4_files[@]}"; do
    # Skip the output file if it already exists
    if [[ "$file" != "output.mp4" && -f "$file" ]]; then
      echo "Adding file to list: $file"
      echo "file '$file'" >> "$temp_file"
    else
      echo "Skipping file: $file"
    fi
  done
fi

# Check if any files were added to the list
if [[ -s "$temp_file" ]]; then
  echo "==============================================="
  echo "Concatenating the following MP4 files:"
  cat "$temp_file"
  echo "==============================================="
  
  echo "Starting ffmpeg concatenation process..."
  # Concatenate the files using ffmpeg into a temporary output
  temp_output="temp_output.mp4"
  ffmpeg -v verbose -f concat -safe 0 -i "$temp_file" -c copy "$temp_output"
  
  if [[ $? -eq 0 ]]; then
    echo "==============================================="
    echo "Concatenation complete! Temporary file created."
    echo "Converting to SD format to reduce file size..."
    
    # Convert to SD format (854x480 resolution)
    ffmpeg -i "$temp_output" -vf "scale=854:480" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4
    
    if [[ $? -eq 0 ]]; then
      echo "==============================================="
      echo "Conversion complete! Output saved as output.mp4"
      echo "Original size: $(du -h "$temp_output" | cut -f1)"
      echo "Reduced size: $(du -h output.mp4 | cut -f1)"
      
      # Clean up temporary output file
      rm -f "$temp_output"
      echo "Temporary output file removed."
    else
      echo "Error: SD conversion failed."
      echo "The concatenated file is still available as: $temp_output"
    fi
  else
    echo "Error: ffmpeg concatenation failed."
  fi
else
  echo "No valid MP4 files found to concatenate."
fi

# Remove the temporary file
echo "Cleaning up temporary file..."
rm -f "$temp_file"
echo "Done! Temporary file removed." 
```

# インストール

- 実行可能ファイルにする
```
% chmod +x concat_mp4.zsh
```

- ~/bin に格納する

```
% mkdir -p ~/bin
% mv concat_mp4.zsh ~/bin/concat_mp4
```

- .zshrcにパスを通す

```
% echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
```

- .zshrc を読み込む
```
% source ~/.zshrc
```

# 使い方

- ターミナルを開き、zshでmp4ファイルが格納されているフォルダに移動する
- 実行する
```
% concat_mp4
```