Created
August 15, 2025 16:19
-
-
Save mrbrainz/2e960538af8ef0e12d46a299068149b7 to your computer and use it in GitHub Desktop.
Shell script to stitch Samsung Gear 360 videos to make them viewable in a player like VLC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # This script processes a folder of MP4 videos recorded on a Samsung Gear 360 so they can be watched in a supported | |
| # 360 video player or uploaded to a site like Facebook | |
| # | |
| # Usage: ./360.sh <input_folder> <output_folder> | |
| # | |
| # Obvs. don't forget to make the script executable with chmod | |
| # | |
| # Requires FFMPEG and EXIFtool to be installed. My recommendation would be to install these using Brew. | |
| # Exit immediately on errors | |
| set -e | |
| # Check arguments | |
| if [ "$#" -ne 2 ]; then | |
| echo "Usage: $0 <input_folder> <output_folder>" | |
| exit 1 | |
| fi | |
| INPUT_DIR="$1" | |
| OUTPUT_DIR="$2" | |
| # pano.xml content inlined here | |
| PANO_XML_CONTENT='<?xml version="1.0"?> | |
| <rdf:SphericalVideo xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:GSpherical="http://ns.google.com/videos/1.0/spherical/"> | |
| <GSpherical:Spherical>true</GSpherical:Spherical> | |
| <GSpherical:Stitched>true</GSpherical:Stitched> | |
| <GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType> | |
| </rdf:SphericalVideo>' | |
| # Create output directory if it doesn’t exist | |
| mkdir -p "$OUTPUT_DIR" | |
| # Find mp4/MP4 files | |
| shopt -s nullglob nocaseglob | |
| files=("$INPUT_DIR"/*.mp4) | |
| if [ ${#files[@]} -eq 0 ]; then | |
| echo "No MP4 files found in $INPUT_DIR" | |
| exit 0 | |
| fi | |
| # Loop over MP4 files | |
| for infile in "${files[@]}"; do | |
| filename=$(basename "$infile") | |
| name="${filename%.*}" | |
| outfile="$OUTPUT_DIR/${name}_fe.mp4" # force lowercase .mp4 | |
| echo "Processing: $filename" | |
| # Run ffmpeg quietly (warnings & errors only) | |
| ffmpeg -hide_banner -loglevel warning -y -i "$infile" \ | |
| -vf v360=dfisheye:e:yaw=0:ih_fov=192:iv_fov=192 \ | |
| -c:v h264_videotoolbox -b:v 40000k -bufsize 5000k \ | |
| -c:a copy "$outfile" | |
| # Create a temporary pano.xml file | |
| tmp_pano=$(mktemp) | |
| echo "$PANO_XML_CONTENT" > "$tmp_pano" | |
| # Run exiftool using temp pano.xml | |
| exiftool -tagsfromfile "$tmp_pano" -api largefilesupport=1 -all:all -overwrite_original "$outfile" >/dev/null | |
| # Remove temp pano.xml | |
| rm -f "$tmp_pano" | |
| # Preserve original file timestamps | |
| touch -r "$infile" "$outfile" | |
| echo "Done: $outfile" | |
| done | |
| echo "All files processed successfully." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment