Skip to content

Instantly share code, notes, and snippets.

@jordicenzano
Last active July 23, 2018 13:47
Show Gist options
  • Save jordicenzano/d8aeac1a2eaf088a61ace5f472388517 to your computer and use it in GitHub Desktop.
Save jordicenzano/d8aeac1a2eaf088a61ace5f472388517 to your computer and use it in GitHub Desktop.
Convert .ts chunk to .fmp4 (HLS) chunk (NOT FINISHED YET)
#!/usr/bin/env bash
# Assumimng input .ts with 2 tracks:
# Video: h264
# Audio: AAC
# Check ffmpeg and BENTO mp4extract are installed and in the PATH
if ! [ -x "$(command -v ffmpeg)" ]; then
echo 'Error: ffmpeg is not installed.' >&2
exit 1
fi
if ! [ -x "$(command -v mp4extract)" ]; then
echo 'Error: mp4extract (BENTO) is not installed.' >&2
exit 1
fi
# Read arguments
if [ "$#" -ne 2 ]; then
echo "The usage is:"
echo "./tsmp4.sh INPUT_TS_DIR OUTPUT_FMP4_DIR"
echo "Example: ./ts2fmp4.sh ./input_ts ./output_fmp4"
exit 1
fi
input_ts_dir=$1 #ts-src
output_fmp4_dir=$2 #mp4-converted
# Ini var
is_first_segment='yes'
# Read & transform all .ts from the input dir
for i in $input_ts_dir/*.ts; do
name=`echo "${i%.*}"`;
srcname="$name.ts"
filename=$(basename $name)
dstname_fmp4="$output_fmp4_dir/$filename.mp4"
fragname_fmp4="$output_fmp4_dir/$filename.m4s"
dstname_init="$output_fmp4_dir/init.mp4"
tmpname_init="$output_fmp4_dir/tmp.bin"
echo "Source file: $srcname";
echo "Destination fmp4 file: $dstname_fmp4";
# Notice that we copy video but we REtranscode the audio
#TODO Fix annexB problem!
ffmpeg -y -i $srcname -vcodec copy -f mp4 -movflags +empty_moov+omit_tfhd_offset+global_sidx+default_base_moof -frag_size 1000000000 $dstname_fmp4
# 1- Create init.mp4: Getting 1st segment and extracting (ftyp and moov)
if [ "$is_first_segment" = "yes" ]; then
echo "Generating $dstname_init";
#NOTE: mp4edit does NOT work outside moov atom (BENTO bug)
rm -y $dstname_init
mp4extract ftyp $dstname_fmp4 $dstname_init
mp4extract moov $dstname_fmp4 $tmpname_init
cat $tmpname_init >> $dstname_init
rm $tmpname_init
is_first_segment='no'
fi
# 2- Clean up all segments: Remove ftyp, moov, and mfra (keep just sidx, moof, and mdat)
echo "Cleaning segment $fragname_fmp4";
# Assuming 2 tracks
mp4extract sidx[0] $dstname_fmp4 $fragname_fmp4
mp4extract sidx[1] $dstname_fmp4 $tmpname_init
cat $tmpname_init >> $fragname_fmp4
rm $tmpname_init
mp4extract moof $dstname_fmp4 $tmpname_init
cat $tmpname_init >> $fragname_fmp4
rm $tmpname_init
mp4extract mdat $dstname_fmp4 $tmpname_init
cat $tmpname_init >> $fragname_fmp4
rm $tmpname_init
# PROBLEM: 1st segment plays ok 2nd segment breaks (continuity indicators), WORKS WITH A DISCO IN THE MIDLE!!!!!!!!!
# Manual steps to fix disco between segments
# We should rewrite:
# tfdt->baseMediaDecodeTime with the PTS for the 1st frame in that chunk
# And perhaps sidx->baseMediaDecodeTime (not sure about this one) (it works without sidx too!!!!)
# And perhaps mfhd->sequenceNumber (not sure about this one)
# Tested ffprobe get last video/autio PTS1 and dur1 from chunk1, and added manually (hex editor) to segment2 tfdt->baseMediaDecodeTime = PTS1+dur1, and fixed mfhd->sequenceNumber
# RESULT: Plays good safari and QT BUT audio GLITCH!!!!!! (PASSES mediastreamvalidator tests!!!!)
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment