Split MPEG video from command line?

6

I have a homemade DVD that I'm effectively trying to insert chapters into and rearrange - the original author burned it as one long chapter, and I'd like to rip it into smaller pieces and re-encode it into a new DVD. I ripped the DVD with the following command:

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

I'm running Gentoo Linux with mplayer version 1.0-rc2_p20090731 (the latest available in Portage).

I have a list of times that the chapters are supposed to span (for example 30:11-33:25), so my first thought was to rip the entire DVD and use mpgtx to cut out certain pieces of the file. My issue is that running mpgtx -i on the file reports quite a few timestamp jumps:

Time stamps jumped from 59.753789 to 0.001622 at position 1d29800
Time stamps jumped from 204963823030450.343750 to 31.165900 at position 2d4f800
Time stamps jumped from 60.077878 to 0.001622 at position 43cc000 
Time stamps jumped from 60.024233 to 0.001622 at position 65c5000
Time stamps jumped from 204963823068631.718750 to 52.549244 at position 7fd1000

I've tried to fix the indexes using:

mencoder raw.vob -oac copy -ovc copy -forceidx -o fixed.vob -of mpeg

But mpgtx will still report timestamp issues. My immediate question: is there a way to take the ripped movie I have and correct its timestamps so I can cut it with mpgtx? If I can get that one issue out of the way, building the rest of the DVD will be smooth sailing.

If it's not possible to fix the timestamps on this file: is there a better way to rip small chunks of the DVD into separate files for recompilation later? I'd very much like this to be done on Linux, and it'd be even better if I could script it somehow (feed in a list of start and end positions, or start times and durations, and get out a series of ripped files). If need be, I also have a Mac OS X machine available, but no Windows.

Edit: I wound up finding another solution involving HandBrake and ffmpeg (with help from this question), but the question stands.

Edit again: Turns out my other solution didn't quite work - the audio desynchronized by about five seconds, in about half of my cut mpgs - so I'm back to square one. Anyone?

Tim

Posted 2009-08-28T04:29:57.193

Reputation: 522

Answers

8

FFmpeg will do this for you.

Your command might look something like this:

Code: ffmpeg -i input.mpg -ss 00:00:10 -t 00:00:30 out1.mpg -ss is the start point in hh:mm:ss from the beginning of your video file

-t is the length of time in hh:mm:ss of your new segment.

So, in the above example, you're starting 10 seconds in from the beginning of the original file and ending 30 seconds later.

If you want to create multiple parts in one pass then the following should work:

Code: ffmpeg -i input.mpg -ss 00:00:10 -t 00:00:30 out1.mpg -ss 00:00:35 -t 00:00:30 out2.mpg In this example, the first segment is the same as the first example, but you're also creating a second file starting at 35 seconds in and being 30 seconds long.

.

TomB

Posted 2009-08-28T04:29:57.193

Reputation: 323

yeah ffmpeg has proven more stable for me than mencoder for splitting streams. Note also that if you make every frame an i-frame, you can split quite precisely: ref: http://en.wikibooks.org/wiki/Mplayer#Split.2Fsub-section_videos here is also a long list here: https://spreadsheets.google.com/ccc?key=0AjWmZ0umsuZHdHNzZVhuMTkxTHdYbUdCQzF3cE51Snc&hl=en

– rogerdpack – 2010-12-03T07:15:39.983

1

I once hacked this together for getting video of a 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
}

The a variable takes the position values where the jump occurs and then just uses dd to slice the file into pieces at those positions. The result are then separate mpeg files for every chapter, as the jump occurred whenever the recording was stopped and restarted. The resulting mpeg files where jump free and could then be processed as usual.

The script itself actually doesn't call dd, it just outputs the dd commands needed to slice the file into pieces.

Grumbel

Posted 2009-08-28T04:29:57.193

Reputation: 3 100

0

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

user1855805

Posted 2009-08-28T04:29:57.193

Reputation: 41