萬盛學電腦網

 萬盛學電腦網 >> 服務器教程 >> linux中使用ffmpeg 無損剪切/拼接視頻程序

linux中使用ffmpeg 無損剪切/拼接視頻程序

   剪切/拼接視頻文件是一種常見需求。在線視頻網站現在往往將一個視頻文件分割成 n 段,以減少流量消耗。使用 DownloadHelper/DownThemAll 這類工具下載下來的往往就是分割後的文件。能實現剪切/拼接視頻文件的工具多種多樣,但往往都需要進行視頻重編碼(transcoding),這就不可避免的帶來了視頻質量上的損耗,更不用提那長的令人發指的轉換時間了…

  其實借助 ffmpeg 我們就可以在不進行視頻重編碼的情況下完成此類任務:

  剪切:

 代碼如下   ffmpeg -i input.mp4 -ss **START_TIME** -t **STOP_TIME** -acodec copy -vcodec copy output.mp4

  其中 START_TIME/STOP_TIME 的格式可以寫成兩種格式:

  以秒為單位計數: 80

  時:分:秒: 00:01:20

  拼接 :

  拼接的情況稍微復雜些,我們需要將需要拼接的視頻文件按以下格式保存在一個列表 list.txt 中:

 代碼如下   file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

  相應的命令為:

 代碼如下   ffmpeg -f concat -i **list.txt** -c copy output.mp4

  由於不需要重編碼,這兩條命令幾乎是即時完成的。

  方便起見,我寫了一個腳本來簡化操作。放在 github 上,請自取:

 代碼如下  

#!/bin/bash
#cut/join videos using ffmpeg without quality loss

if [ -z $1 ] || [ -z $2 ]; then
   echo "Usage:$0 c[ut] seconds <File>"
   echo "   eg. $0 c 10 80 example.mp4"
   echo "   eg. $0 c 00:00:10 00:01:20 example.mp4"
   echo "Usage:$0 j[oin] <FileType>"
   echo "   eg. $0 j avi"
   exit
fi

case "$1" in
   c)
      echo "cuttig video..."
      fileName=$(echo $4 | cut -f 1 -d '.')
      fileType=$(echo $4 | cut -f 2 -d '.')
      ffmpeg -i $4 -ss $2 -t $3 -acodec copy -vcodec copy $fileName-$2-$3.$fileType
      ;;
   j)
      echo "joinning videos..."
      rm temp_list.txt      
      for f in ./*.$2; do echo "file '$f'" >> temp_list.txt; done
      printf "file '%s'\n" ./*.$2 > temp_list.txt
      ffmpeg -f concat -i temp_list.txt -c copy output.$2
      rm temp_list.txt
      ;;
   *)
      echo "wrong arguments"
      ;;
esac
exit

  以上拼接操作生效的前提是,所有視頻文件的格式編碼相同,如果需要拼接不同格式的視頻文件可以借助以下腳本

 代碼如下  

# change this to what you need !!!
EXTRA_OPTIONS='-vcodec libx264 -crf 23 -preset medium -acodec aac -strict experimental -ac 2 -ar 44100 -ab 128k'
 
################################################################################
#
# NO NEED TO TOUCH ANYTHING AFTER THIS LINE!
#
################################################################################
 
# the version of the script
VERSION=1.3
 
# location of temp folder
TMP=/tmp
 
################################################################################
 
echo "MultiMedia Concat Script v$VERSION (mmcat) - A script to concatenate multiple multimedia files."
echo "Based on FFmpeg - www.ffmpeg.org"
echo "Don't forget to edit this script and change EXTRA_OPTIONS"
echo ""
 
################################################################################
# syntax check (has to have at least 3 params: infile1, infile2, outfile
################################################################################
if [ -z $3 ]; then
 echo "Syntax: $0 <input1> <input2> <input3> ... <output>"
 exit 1
fi
 
################################################################################
# get all the command line parameters, except for the last one, which is output
################################################################################
# $first  - first parameter
# $last   - last parameter (output file)
# $inputs - all the inputs, except the first input, because 1st input is
#           handled separately
################################################################################
first=${@:1:1}
last=${@:$#:1}
len=$(($#-2))
inputs=${@:2:$len}
 
# remove all previous tmp fifos (if exist)
rm -f $TMP/mcs_*
 
################################################################################
# decode first input differently, because the video header does not have to be
# kept for each video input, only the header from the first video is needed
################################################################################
mkfifo $TMP/mcs_a1 $TMP/mcs_v1
 
ffmpeg -y -i $first -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 $TMP/mcs_a1 2>/dev/null </dev/null &
ffmpeg -y -i $first -an -f yuv4mpegpipe -vcodec rawvideo $TMP/mcs_v1 2>/dev/null </dev/null &
 
# if you need to log the output of decoding processe

copyright © 萬盛學電腦網 all rights reserved