Skip to content

Instantly share code, notes, and snippets.

@bjou
Last active December 20, 2015 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bjou/6097170 to your computer and use it in GitHub Desktop.
Save bjou/6097170 to your computer and use it in GitHub Desktop.
ffmpeg_hd2sd_transcode_segment
# convert HD video to SD and transcode in one-shot
ffmpeg -i video.ts -preset ultrafast -y [-loglevel quiet] -aspect 16:9 -s 640:360 video.mp4
# batch segment the video in one-shot (no looped seeking)
# NOTES: "-vcodec" and "-acodec" can be changed to preferred stream types, e.g. libx264 and libfaac, respectively
# "-vbsf h264_mp4toannexb" optionally allows for broken mp4's to still get parsed
ffmpeg -i video.mp4 -vcodec copy -acodec copy -map 0 [-vbsf h264_mp4toannexb] [-loglevel quiet] -f segment -segment_format mp4 -segment_times <time_sec_1>,<time_sec_2>,<time_sec_3>,<...> output%02d.mp4
# TODO: needs further investigation on segmentation accuracy; cutting may still happen on i-frames due to keyframe-level accuracy, but this may have been solved by mpegts-to-mp4 transcoding
@bjou
Copy link
Author

bjou commented Jul 28, 2013

Here's a script for directly parsing triple-marker files and passing it as a parameter to segmentation:

#!/usr/bin/env bash
#
# $1 : path to mpegts file
# $2 : path to triple marker file
# $3 : output path + prefix (e.g. /path/for/output/prefix)

T="$(date +%s%N)"

ffmpeg -i $1 -preset ultrafast -y -loglevel quiet -aspect 16:9 -s 640:360 video.mp4

ffmpeg -i video.mp4 -vcodec copy -acodec copy -map 0 -vbsf h264_mp4toannexb \
 -loglevel quiet -f segment -segment_format mp4 \
 -segment_times `cut -d' ' -f1 $2 | tail -n +2 | tr ',' '.' | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }' | tr '\n' ',' | sed 's/.$//'` \ 
 $3%02d.mp4

T="$(($(date +%s%N)-T))"
S="$((T/1000000000))"
M="$((T/1000000))"
printf "Time elapsed: %02d:%02d:%02d:%02d.%03d\n" "$((S/86400))" "$((S/3600%24))" "$((S/60%60))" "$((S%60))" "${M}"

The portion that does the actual parsing is (it assumes the first column of the file contains cut times, i.e. beginning of new segments):

cut -d' ' -f1 $2 | \
 tail -n +2 | tr ',' '.' | \
 awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }' | \
 tr '\n' ',' | sed 's/.$//'

Example usage:

bash segment.sh /ptvn/RawVideos/20130725/CNN_Newsroom_20130725_1400.ts \
 /ptvn/storyboundary_ccasr/CNN_Newsroom_20130725_1400/CNN_Newsroom_20130725_1400.aligned/CNN_Newsroom_20130725_1400.cc_tripleColumbia \
 /ptvn/tmp/test_segment/test_out

@bjou
Copy link
Author

bjou commented Jul 29, 2013

tail -n +2 in the triple marker parsing should be ignored if the first line of the file is still usable

@bjou
Copy link
Author

bjou commented Jul 29, 2013

To change to cutting by frames use -segment_frames instead of -segment_times, and change the triple marker parsing to:

cut -d' ' -f1 $2 | \
 tr ',' '.' | \
 awk -F: '{ printf "%d,",((($1 * 3600) + ($2 * 60) + $3) * 29.97) }' | \
 sed 's/.$//'

(assuming the frame rate of the video is 29.97 fps and the first line of the triple marker file is valid)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment