Blog-Archiv

Mittwoch, 18. September 2024

Slow Motion or Time Lapse with ffmpeg

Sometimes you want to slow down or speed up your H264 codec video (mind that this works smoothly only for videos without audio-track!). Here is a UNIX shell-script to do this losslessly when ffmpeg is installed. If you pass e.g. myVideo.mp4 as first parameter, the script will generate a new video-file named myVideo_timed.mp4 in the directory where the original video resides.

fileMarker=timed

[ -z "$1" -o ! -f "$1" ] && {
	echo "SYNTAX: $0 videoFile [framesPerSecond]" >&2
	echo "	Slows down or speeds up given video, creating an xxx_$fileMarker.mp4 file." >&2
	echo "	framesPerSecond default is 15, which is half speed of normal 30 fps." >&2
	exit 1
}

sourceVideo=$1
sourceDir=`dirname \$sourceVideo`
sourceFile=`basename \$sourceVideo`
filename=${sourceFile%.*}	# filename without extension
extension=${sourceFile#*.}	# extension without filename
targetVideo=$sourceDir/${filename}_$fileMarker.$extension

framesPerSecond=15
[ -n "$2" ] && framesPerSecond=$2

tempRawFile=raw.h264

cleanup()	{
	rm -rf $tempRawFile
}
error()	{
	cleanup
	exit $1
}

# copy the video to a raw bitstream format
ffmpeg -v error -y -i $sourceVideo -map 0:v -c:v copy -bsf:v h264_mp4toannexb $tempRawFile || error 2

# generate new timestamps while muxing to a container
ffmpeg -v error -y -fflags +genpts -r $framesPerSecond -i $tempRawFile -c:v copy $targetVideo || error 3

cleanup

echo "Created $targetVideo"

Normally the frames-per-second value is something like 30. By default the script will slow down the video by 50% when you do not pass an explicit FPS-value as second argument to the script call (framesPerSecond=15). If you pass a value of 60, the video will play in double speed.




Dienstag, 17. September 2024

Add or Remove Audio to or from Video with ffmpeg

Here are lossless UNIX shell-scripts to create a new video from a given video, either by adding a given audio track, or by removing the existing audio track. The scripts ensure that the source-video is not overwritten by the newly created one.

Please mind that expressions like ${sourceFile%.*} and ${sourceFile#*.} may be not supported by some UNIX shell implementations!

Add Audio to Video

fileMarker=audio

[ -z "$1" -o ! -f "$1" -o -z "$2" -o ! -f "$2" ] && {
	echo "SYNTAX: $0 videoFile audioFile" >&2
	echo "	Adds given audio track to given video, creating an xxx_$fileMarker.mp4 file." >&2
	exit 1
}

sourceVideo=$1
sourceDir=`dirname \$sourceVideo`
sourceFile=`basename \$sourceVideo`
filename=${sourceFile%.*}	# filename without extension
extension=${sourceFile#*.}	# extension without filename
targetVideo=$sourceDir/${filename}_$fileMarker.$extension

audio=$2

ffmpeg -v error -y -i $sourceVideo -i $audio -map 0:v -map 1:a -c:v copy -c:a copy $targetVideo

echo "Created $targetVideo"

The -c:v copy option guarantees losslessness.


Remove Audio from Video

fileMarker=noaudio

[ -z "$1" -o ! -f "$1" ] && {
	echo "SYNTAX: $0 videoFile" >&2
	echo "	Removes audio track(s) from given video, creating an xxx_$fileMarker.mp4 file." >&2
	exit 1
}

sourceVideo=$1
sourceDir=`dirname \$sourceVideo`
sourceFile=`basename \$sourceVideo`
filename=${sourceFile%.*}	# filename without extension
extension=${sourceFile#*.}	# extension without filename
targetVideo=$sourceDir/${filename}_$fileMarker.$extension

ffmpeg -v error -y -i $sourceVideo -an -c:v copy $targetVideo

echo "Created $targetVideo"

Important are both -an and -c:v copy options. The -an excludes any audio track from copying, the -c:v copy avoids the ffmpeg default re-encoding of the video (makes the copy lossless). If you pass e.g. a file named myVideo.mp4 to this script, it will generate myVideo_noaudio.mp4 as result, residing in the directory where the original video is.




List of my ffmpeg Scripts

Here is a list of all my ffmpeg Blogs. You can copy any source-code freely. Use CygWin as script execution environment on WINDOWS.

  1. Video Cut Automation with ffmpeg (2020-09-12)
  2. Video Title Creation with ffmpeg (2020-09-16)
  3. Another Video Title with ffmpeg (2020-10-06)
  4. Utility Scripts for ffmpeg (2020-10-11)
  5. Crossfade Transition Between Two Videos with ffmpeg (2021-01-05)
  6. Rotating Videos with ffmpeg (2021-10-04)
  7. Scroll Text Over Image with ffmpeg (2022-03-25)
  8. Combine Scroll Text Videos with ffmpeg (2022-03-30)
  9. Image to Video with ffmpeg (2023-03-20)
  10. Brighten or Darken a Video with ffmpeg (2023-07-08)
  11. Using ffplay for Writing Cutting Plans (2024-09-16)
  12. Add or Remove Audio to or from Video with ffmpeg (2024-09-17)
  13. Slow Motion or Time Lapse with ffmpeg (2024-09-18)

Also this may be useful for formatting text on scroll-text videos:




Montag, 16. September 2024

Using ffplay for Writing Cutting Plans

The widely used ffmpeg library is a complex commandline-oriented video software. It also contains a very basic video viewer named ffplay which may be useful for certain purposes. After installing ffmpeg, you can play a video using following command from some terminal-window:

ffplay pathToSomeVideo.mp4

When you run this player, you will see just the video screen with no control-buttons at all. That doesn't mean that you can't stop the video, seek to some position, or display single frames, but everything is quite limited. On the ffmpeg home page you can find documentation about available keyboard commands. Here are some explanations about the most important ones.

  • The 'p' (→pause) or Space key stops the video. Pressing it again ends the pause, so it is like a Start/Stop button.

  • The 's' (→step) key also stops the video, but if already stopped, it goes to the next frame image. Unfortunately there is no "step back one frame" command...

  • If you right-click with the mouse into the video screen, ffplay will seek to a video position proportional to the click's horizontal coordinate inside the screen's width. That means if you right-click into the (horizontal) middle of the screen, ffplay will seek to the middle of the video, if you right-click near the left border, the video will continue near its beginning. You will see output like this on console:
    Seek to 51% ( 0:02:17) of total duration ( 0:04:27)       B f=0/0
    The pause-state will not be changed by this action, i.e. when the video was running, it will continue at clicked position, when it was stopped, it will display the frame at clicked position.

  • The Cursor-Left key will seek backward 10 seconds, Cursor-Right will seek forward 10 seconds. The pause-state will not be changed by this action.

  • The Cursor-Down key will seek backward 1 minute, Cursor-Up will seek forward 1 minute. Useful for quickly winding back to start on short clips. The pause-state will not be changed by this action.

  • The 'q' (→quit) key end the ffplay run.

While playing or stepping, on the console (terminal window) where you started ffplay from, you will see some output like

  42.39 A-V: -0.049 fd=   3 aq=   66KB vq= 2455KB sq=    0B f=0/0

I could not find documentation about this line, but obviously the first number ('42.39') gives the precise time in seconds where the video currently is.
So, if you want to cut out certain frames from a video very precisely, I would suggest following workflow:

  1. Run "ffplay TheVideo.mp4" from command line.
  2. Press the 's' key to go to the frame you want to find, or 'p' and right-click to go near that position.
  3. If you found the frame you want to cut out, copy the seconds display in console window to your cutting plan; this is your clip's begin.
    Skip frames as long as you want to keep them, then again copy the seconds display in console window to your cutting plan; this is your clip's end. As much as I observed, the frame at the end time will not be in the clip anymore.

If you are interested in using a cutting-plan to cut videos with ffmpeg, my UNIX shell-scripts may be useful for you (also running on WINDOWS via CygWin). Read my Blogs here:

You can copy any source-code of my scripts freely.
UPDATE: My newest Blog contains a complete list of my passed ffmpeg Blogs!