Spyke

Syndicated from the fediverse. Read and engage on the original instance.

View original on sh.itjust.works

1 reply

I've been using ffmpeg for decades, and while it's not the easiest tool to understand the logic of the command line arguments of when you first dive into it, once you "get it", it's quite fucking brilliant.

Case in point: only 3 days ago, I made a shell script to take a bunch of 360° photographs shot at regular intervals and concatenate them into a timelapse video file. The single ffmpeg command:

  • Rescales the input images to a more manageable resolution for 360° video players
  • Denoises the images by blending each image with its two "neighbors" before and after it
  • Reprojects the scene by yawing the POV some 40° to the right to face the subject of the video
  • Color-corrects the images to lift the shadows and the midtones a bit because the images were shot at dusk and were underexposed
  • Superimpose the time of the day at which the individual frames were shot from the image files' timestamps in the 360° view at a particular spot in the sphere
  • Speeds up the video 90x

All that in ONE SINGLE COMMAND.

ffmpeg is the most powerful tool ever! I fucken love it.

And the entire supporting shell script around it is 76 lines. That's really not a lot of shell script to do that much ultra-specialized video editing... This would never be possible without ffmpeg.

(And here's the script If you're curious:)

#!/bin/bash  
FIRST_IMG_IDX=4  
LAST_IMG_IDX=11690  

FINAL_VIDEO=timelapse	# name only, no extension  
FORMAT=webm		# "mp4" or "webm"  
SPEEDUP=90  
WIDTH=4096  
HEIGHT=2048  
TIMESTAMP_FONT_SIZE=24  
TIMESTAMP_X=2048  
TIMESTAMP_Y=1300  
DENOISE_ARGS="tmedian=radius=1"  
COLOR_CORRECTION_ARGS="colorbalance=rs=.08:gs=.08:bs=.08:rm=.04:gm=.04:bm=.04"  
YAW_CORRECTION=40.43  
MP4_BITRATE=33000k  
VP9_QUALITY=30		# Typically 28-32 - lower is better quality  
FRAMERATE=15  

INPUT_FILES_TSTAMPS=$(stat --printf='%n:%Y\n' *.JPG | sort -t":" -n -k2 | gawk 'match($1, /[0-9]+/, t) {if (t[0] >= '${FIRST_IMG_IDX}' && t[0] <= '${LAST_IMG_IDX}') {print $0}}')  

NB_IMGS=$(printf '%s\n' ${INPUT_FILES_TSTAMPS} | wc -l)  
FIRST_IMG_TSTAMP=$(printf '%s\n' "${INPUT_FILES_TSTAMPS}" | gawk 'BEGIN {FS=":"} NR==1 {print $2}')  
LAST_IMG_TSTAMP=$(printf '%s\n' "${INPUT_FILES_TSTAMPS}" | gawk 'BEGIN {FS=":"} {t=$2} END {print t}')  
AVG_TIME_BETWEEN_IMGS=$(gawk -v n=${NB_IMGS} -v f=${FIRST_IMG_TSTAMP} -v l=${LAST_IMG_TSTAMP} 'BEGIN {printf "%0.0f", (l-f) / (n-1)}')  

if [ ${FORMAT} == "mp4" ]; then  
  ENCODING_ARGS="-c:v libx264 -b:v ${MP4_BITRATE} -pix_fmt yuv420p"  
else  
  ENCODING_ARGS="-c:v libvpx-vp9 -crf ${VP9_QUALITY} -b:v 0 -pix_fmt yuv420p"  
fi  

for PASS in 1 2; do  

  if [ ${PASS} == 1 ]; then  
    OUTFILE=/dev/null  
  else  
    OUTFILE=${FINAL_VIDEO}.${FORMAT}  
  fi  

  ffmpeg -f concat -safe 0 -i <(printf '%s\n' "${INPUT_FILES_TSTAMPS}" | gawk -v d=${AVG_TIME_BETWEEN_IMGS} 'BEGIN {FS=":"} {printf("file '\'${PWD}'/%s'\''\nduration %s\n", $1, d)}') -vf "\  
			scale=${WIDTH}:${HEIGHT}, \  
			${DENOISE_ARGS}, \  
			${COLOR_CORRECTION_ARGS}, \  
			v360=\  
				input=equirect: \  
				output=equirect:yaw=${YAW_CORRECTION}, \  
			drawtext=\  
				fontsize=${TIMESTAMP_FONT_SIZE}: \  
				fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf: \  
				text='%{pts\:localtime\:${FIRST_IMG_TSTAMP}\:%H\\\\\:%M}': \  
				fontcolor=white: box=1: [email protected]: boxborderw=5: \  
				x=${TIMESTAMP_X}-text_w/2: \  
				y=${TIMESTAMP_Y}-text_h-5, \  
			setpts=PTS/${SPEEDUP} \  
		" -r ${FRAMERATE} ${ENCODING_ARGS} -y -pass ${PASS} -passlogfile timelapse_2_pass.log -f ${FORMAT} ${OUTFILE}  

done  

if [ "${FORMAT}" == "webm" ]; then  
  mkvpropedit ${FINAL_VIDEO}.${FORMAT} --tags track:v1:spherical_xmp_metadata.xml  
else  
  exiftool -overwrite_original \  
		-XMP-GPano:UsePanoramaViewer=true \  
		-XMP-GPano:ProjectionType=equirectangular \  
		-XMP-GPano:PoseHeadingDegrees=0.0 \  
		-XMP-GPano:PosePitchDegrees=0.0 \  
		-XMP-GPano:PoseRollDegrees=0.0 \  
		-XMP-GPano:InitialViewHeadingDegrees=0.0 \  
		-XMP-GPano:InitialViewPitchDegrees=0.0 \  
		-XMP-GPano:InitialViewRollDegrees=0.0 \  
		-XMP-GSpherical:Spherical=true \  
		-XMP-GSpherical:Stitched=true \  
		-XMP-GSpherical:ProjectionType=equirectangular \  
		${FINAL_VIDEO}.${FORMAT}  
fi  
2

You reached the end

FFmpeg 9.0 Released With More Vulkan Acceleration, Animated WebP & More AMD AMF | Spyke