コマンドラインから MPEG ビデオを分割しますか?

コマンドラインから MPEG ビデオを分割しますか?

自作の DVD があり、これにチャプターを挿入して並べ替えようとしています。元の作者はそれを 1 つの長いチャプターとして焼いたのですが、それを小さな部分にリッピングして新しい DVD に再エンコードしたいと思っています。次のコマンドで DVD をリッピングしました。

mplayer dvd:// -dvd-device /dev/sr2 -dumpstream -dumpfile raw.vob

私は Gentoo Linux を mplayer バージョン 1.0-rc2_p20090731 (Portage で利用可能な最新バージョン) で実行しています。

チャプターがカバーする時間のリスト(例えば30:11-33:25)があるので、最初に考えたのはDVD全体をリッピングしてmpgtxファイルの特定の部分を切り取ります。私の問題は、mpgtx -iファイルを実行すると、かなりの数のタイムスタンプのジャンプが報告されることです。

タイムスタンプは、位置 1d29800 で 59.753789 から 0.001622 にジャンプしました。
タイムスタンプは、位置 2d4f800 で 204963823030450.343750 から 31.165900 にジャンプしました。
タイムスタンプは、位置 43cc000 で 60.077878 から 0.001622 にジャンプしました。
タイムスタンプは、位置 65c5000 で 60.024233 から 0.001622 にジャンプしました。
タイムスタンプは、位置 7fd1000 で 204963823068631.718750 から 52.549244 にジャンプしました。

以下を使用してインデックスを修正しようとしました:

mencoder raw.vob -oac コピー -ovc コピー -forceidx -o fixed.vob -of mpeg

しかし、mpgtx は依然としてタイムスタンプの問題を報告します。すぐに疑問に思うのは、リッピングしたムービーのタイムスタンプを修正して、mpgtx でカットする方法はあるかということです。この 1 つの問題を解決できれば、DVD の残りの部分の作成はスムーズに進むでしょう。

このファイルのタイムスタンプを修正できない場合、DVD の小さなチャンクを個別のファイルにリッピングして、後で再コンパイルするより良い方法はありますか? これを Linux で実行したいのですが、何らかの方法でスクリプト化できればさらに良いでしょう (開始位置と終了位置のリスト、または開始時間と継続時間を入力して、一連のリッピングされたファイルを取得します)。必要に応じて、Mac OS X マシンも使用できますが、Windows はありません。

編集:私は別の解決策を見つけましたハンドブレーキそしてffmpeg(協力:この質問)、しかし、疑問は残ります。

再度編集:結局、他の解決策はうまくいかなかったようです。カットした mpg の約半分で、オーディオが約 5 秒同期しなくなってしまったので、振り出しに戻ってしまいました。誰かいますか?

答え1

FFmpeg がこれを実行します。

コマンドは次のようになります。

コード: ffmpeg -i input.mpg -ss 00:00:10 -t 00:00:30 out1.mpg -ss はビデオファイルの先頭からの開始点 (hh:mm:ss) です

-t は、新しいセグメントの時間の長さ (hh:mm:ss 形式) です。

したがって、上記の例では、元のファイルの先頭から 10 秒後に開始し、30 秒後に終了します。

1 回のパスで複数のパーツを作成する場合は、次のようにします。

コード: ffmpeg -i input.mpg -ss 00:00:10 -t 00:00:30 out1.mpg -ss 00:00:35 -t 00:00:30 out2.mpg この例では、最初のセグメントは最初の例と同じですが、35 秒目から始まり 30 秒の長さの 2 番目のファイルも作成します。

答え2

私はかつて DVD-RAM のビデオを取得するためにこれをハックしました:

#! /usr/bin/ruby -w

a = [0, 0x37f9800, 0xf3e1800]

filename = "input.vob"

a.each_with_index{|seq_start, i|
  if seq_start % 1024 != 0 then
    puts "Error: Blocksize doesn't match 1024"
  end

  seq_end = a[i+1]

  if seq_end then
    puts "dd if=#{filename} of=chapter#{i+1}.mpeg bs=1024 skip=#{seq_start/1024} count=#{(seq_end - seq_start)/1024}"
  else
    puts "dd if=#{filename} of=chapter#{i+1}.mpeg bs=1024 skip=#{seq_start/1024}"
  end
}

変数aはジャンプが発生した位置の値を取得し、ddそれらの位置でファイルを分割するために使用します。録画が停止して再開されるたびにジャンプが発生したため、結果はチャプターごとに別々の mpeg ファイルになります。結果の mpeg ファイルはジャンプがなく、通常どおり処理できます。

スクリプト自体は実際には を呼び出すことはなく、ファイルを断片に分割するために必要なコマンドddを出力するだけです。dd

答え3

num=1
offset=0
divide="Title:"
divide="Chapter:"
input="VTS_01_1.VOB|VTS_01_2.VOB|VTS_01_3.VOB|VTS_01_4.VOB|VTS_01_5.VOB|VTS_01_6.VOB" 
#|VTS_01_7.VOB|VTS_01_8.VOB|VTS_01_9.VOB"

for len in $(lsdvd -c VIDEO_TS | grep "$divide" | awk -F' +|,' '/Length:/ { print $5 }')
do
 ss=$(date -u -d "@$offset" +%T.%3N)

 echo $num $ss $len
 cd VIDEO_TS
 #ffmpeg -ss $ss -i "concat:$input" -t $len -c copy ../$(printf "%02d" $num).VOB 2>/dev/null
 ffmpeg -ss $ss -i "concat:$input" -map 0:1 -map 0:3 -t $len -acodec copy -vcodec libx264 ../$(printf "%02d" $num).mp4 2>/dev/null
 cd ..

 len=$(date -u -d "1970-01-01 $len" +%s.%3N)
 offset=$( echo "$offset + $len" | bc )
 num=$((num+1))
done

関連情報