동일한 형식으로 인코딩 된 영상이지만, 배포자의 편의를 위해 분리된 파일의 경우 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