동일한 형식으로 인코딩 된 영상이지만, 배포자의 편의를 위해 분리된 파일의 경우 ffmpeg를 이용해서 인코딩 없이 하나로 합칠 수 있다. 폴더 내의 모든 mp4를 검색해서, 같은 서브 폴더 내에 있는 mp4 파일을 이름 순으로 정렬한 후 하나의 mp4파일로 합치는 간단한 스크립트이다. Synology NAS DSM 6, Synocommunity 패키지 센터에서 설치한 ffmpeg 4.2.2 버전에서 시험했다. mp4 파일을 합치는데는 아래 2줄만 있으면 된다.
find "$fileroot" -type f -name "*.mp4" -printf "file '%p'\n" | sort > "fl.txt" $ffmpeg -hide_banner -nostdin -n -f concat -safe 0 -i "fl.txt" -c copy $2"/"$savefilename 2>&1 | tee -a $log
아래 코드에서 log를 저장할 cachepath와 ffmpeg가 설치된 rootpath 부분을 수정한 후 merge.sh로 저장한다. merge.sh /VR /VR_TEMP
로 실행하면, /VR 폴더 아래의 모든 mp4를 검색해서 /VR_TEMP 폴더에 savefilename으로 저장을 한다.
uniquename은 서브 폴더별로 겹치지 않을 문자열을 의미한다. 저장되는 파일명이 동일하면 ffmpeg가 skip하기 때문에, 겹치지 않을 이름이 필요하다. 여기에선 서브 폴더 내의 첫번째 mp4 파일명에서 @ 앞 . 뒤의 수식어를 제거한 것을 uniquename으로 사용한다. uniquename에 _180_sbs라는 VR구분용 수식어와 mp4 확장자를 다시 추가해서 savefilename으로 사용하고 있다.
#!/bin/sh export LANG=en_US.utf8 ## merge.sh /Sourcefolder /Targetfolder -> Param이 없으면 Usage 표시후 종료 if [ $# -ne 2 ]; then echo "Usage: $0 /Sourcefolder /Targetfolder" exit -1 fi ## ffmpeg 및 log 저장 폴더 설정 cachepath="/volume1/Temp" rootpath="/volume1/@appstore/ffmpeg/bin" ffprobe="$rootpath/ffprobe" ffmpeg="$rootpath/ffmpeg" cachedir="$cachepath/cache" logdir="$cachepath/cache" prevfileroot="" ## log파일명으로 사용하기 위해 현재 시간 계산 timestamplog=`date +%s` log="$logdir/merge_$timestamplog.log" echo "----- START ------" | tee -a $log timestamp1=`date +%F_%T` echo $timestamp1 | tee -a $log ## 첫번째 PARAM($1)에 지정된 폴더에서 mp4가 포함된 파일을 찾음. 파일명으로 sort를 함. find $1 -name "*.mp4" -type f | sort | while read f do ## 파일명에서 Path만 분리 fileroot=${f%\/*} ## 서브 폴더에 mp4가 여러 개일 경우를 대비해 폴더 Path가 이전 것과 같은지 비교. if [ "$prevfileroot" != "$fileroot" ]; then echo ================================================================================= | tee -a $log echo processing $f | tee -a $log timestamp2=`date +%F_%T` echo $timestamp2 | tee -a $log ## 폴더 path를 prev로 저장하여, 다음 파일 비교할때 사용. prevfileroot=$fileroot ## 경로 제외한 순수 파일명만 분리 filename=$(basename "$f") ## '@'를 기준으로 파일명 분리 후 2번째 값 선택 -> '.'을 기준으로 파일명 분리 후 1번째 값 선택 uniquename=$(echo "$filename" | cut -f 2 -d '@' | cut -f 1 -d '.' ) ## 특이한 파일명 추가 처리 uniquename=$(echo "$uniquename" | sed 's:-R1_4K::g' | sed 's:-R1::g') echo "root is "$fileroot"" | tee -a $log echo "filename is "$filename"" | tee -a $log echo "uniquename is "$uniquename"" | tee -a $log ## uniquename에 mp4 확장자 및 suffix를 추가하여 파일명 생성 savefilename=$(echo $uniquename"_180_sbs.mp4") ## 서브 폴더 내의 mp4 파일을 이름순으로 정렬한 후, concat 형식으로 변환한 목록을 fl.txt로 저장. find "$fileroot" -type f -name "*.mp4" -printf "file '%p'\n" | sort > "fl.txt" ## fl.txt를 읽어와 concat demuxer를 시도. 두번째 PARAM($2) 아래에 합친 파일 저장. $ffmpeg -hide_banner -nostdin -n -f concat -safe 0 -i "fl.txt" -c copy $2"/"$savefilename 2>&1 | tee -a $log ## 이전 명령어 리턴값을 가져옴. 0이면 성공. fail=$? case "$fail" in "0" ) echo "-----> SUCCESS" | tee -a $log ;; * ) echo "-----> FAIL" | tee -a $log ;; esac ## fl.txt 삭제 rm -rf "fl.txt" timestamp3=`date +%F_%T` echo $timestamp3 | tee -a $log fi done echo "----- END ------" | tee -a $log timestamp4=`date +%F_%T` echo $timestamp4 | tee -a $log exit 0