LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General > LinuxQuestions.org Member Success Stories
User Name
Password
LinuxQuestions.org Member Success Stories Just spent four hours configuring your favorite program? Just figured out a Linux problem that has been stumping you for months?
Post your Linux Success Stories here.

Notices


Reply
  Search this Thread
Old 06-06-2004, 12:08 PM   #1
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Rep: Reputation: 48
Encoding video for VCD and DVD


I recently posted a script that converts video to VCD format using mencoder and some other tools. I've since greatly modified the script so it can handle VCD, SVCD, and DVD output. It's still somewhat of a hack, since bash scripting is not my strong suit, but it may be useful to someone who needs to get video into the right format for burning to CD or DVD.

Requires the following:
  • mplayer for video playback and denoising
  • mjpegtools for encoding and adjusting frame rate
  • perl for string manipulation (if someone could help me remove this dependency, I'd be gracious!)
  • transcode for multiplexing

Here's the script. Save it as 'tovid' and be sure to chmod +x it so you can execute it.

Code:
#!/bin/bash

# Convert any video/audio stream that mplayer can play
# into VCD, SVCD, or DVD-compatible Mpeg output file.
# Arguments: $1 - format: Video CD, Super Video CD, DVD, or VCD-on-DVD [vcd|svcd|dvd]
#            $2 - aspect: Widescreen or full-frame [wide|full]
#            $3 - name of input file
#            $4 - name of output prefix

USAGE="Usage: tovid [vcd|svcd|dvd|dvd-vcd] [wide|full] <input file> <output prefix>"

if [ $# -ne 4 ]; then
  echo $USAGE
  exit 1
elif [[ $1 == "vcd" || $1 == "dvd-vcd" ]]; then
  TGTWIDTH="352"
  TGTHEIGHT="240"
  PALHEIGHT="288"
  FORMAT="VCD"
  VIDFMT="-f 1"
  # For VCD, use VCD sound profile of mp2enc
  if [[ $1 == "vcd" ]]; then
    SNDOPTS="-V"
  # For VCD-on-DVD, use DVD-format audio
  else
    SNDOPTS="-r 48000 -s"
  fi
  MUXOPTS="-m v"
  SUF="m1v"
elif [[ $1 == "svcd" ]]; then
  TGTWIDTH="480"
  TGTHEIGHT="480"
  PALHEIGHT="576"
  FORMAT="SVCD"
  # -d for dummy SVCD scan offsets
  VIDFMT="-f 4 -d"
  SNDOPTS="-V"
  MUXOPTS="-m s"
  SUF="m2v"
elif [[ $1 == "dvd" ]]; then
  TGTWIDTH="720"
  TGTHEIGHT="480"
  PALHEIGHT="576"
  FORMAT="DVD"
  VIDFMT="-f 8"
  SNDOPTS="-r 48000 -s"
  MUXOPTS="-m d"
  SUF="m2v"
else
  echo $USAGE
  exit 1
fi

if [[ $2 == "wide" ]]; then
  ASPECT="WIDE"
elif [[ $2 == "full" ]]; then
  ASPECT="FULL"
else
  echo "$USAGE"
  exit 1
fi

INFILE=$3
OUTPREFIX=$4

# Probe for width, height, and frame rate
tcprobe -i "$INFILE" > fileinfo
CURWIDTH=`grep 'import frame size' fileinfo | \
  perl -e ' $line=<STDIN> ; $line =~ /import frame size: -g (\d+?)x\d+ /  ;  print $1' `
CURHEIGHT=`grep 'import frame size' fileinfo | \
  perl -e ' $line=<STDIN> ; $line =~ /import frame size: -g \d+?x(\d+) /  ;  print $1' `
CURFPS=`grep 'frame rate' fileinfo | \
  perl -e ' $line=<STDIN> ; $line =~ /frame rate: -f (.+?) \[/  ;  print $1' `

echo "Input file is $CURWIDTH x $CURHEIGHT at $CURFPS fps."

# If FPS is already 29.97 (NTSC) or 23.976 (NTSC film), leave it alone
if [[ $CURFPS == "29.970" ]];
then
  echo "Source is 29.970 fps (NTSC). Encoding as NTSC video."
  ADJUSTFPS=""
  VIDFPS="-F 4"
elif [[ $CURFPS == "23.976" ]];
then
  echo "Source is 23.976 fps (NTSC film). Encoding as NTSC film."
  ADJUSTFPS="yuvfps -s 24000:1001 -r 30000:1001 -v 0 |"
  VIDFPS="-F 4"
else
  echo "Source is not at an NTSC frame rate. Adjusting FPS."
  ADJUSTFPS="yuvfps -r 30000:1001 -v 0 |"
  VIDFPS="-F 4"
fi

# Set appropriate aspect ratio for output format
# Widescreen on DVD should be 16:9
[ $ASPECT == "WIDE" ] && [ $FORMAT == "DVD" ] && ASPECTFMT="-a 3"
# Widescreen on VCD/SVCD needs to be padded out to 4:3
[ $ASPECT == "WIDE" ] && [ $FORMAT != "DVD" ] && ASPECTFMT="-a 2"
# Standard (fullscreen) is always 4:3
[ $ASPECT == "FULL" ] && ASPECTFMT="-a 2"

# Estimate existing aspect ratio (integer math!)
ESTASPECT=$(($CURWIDTH * 100 / $CURHEIGHT))
# Tolerances for wide/full aspect ratio (+/- 10% of target)
if [[ $ASPECT == "WIDE" ]];
then
  MINASPECT=160
  MAXASPECT=195
else
  MINASPECT=120
  MAXASPECT=147
fi

# Determine whether any rescaling needs to be done
# If resolution is already the same as the target, do not rescale.
if [[ $CURWIDTH == $TGTWIDTH && $CURHEIGHT == $TGTHEIGHT ]];
then
  echo "Source is already at target resolution ($TGTWIDTH x $TGTHEIGHT)."
  echo "No rescaling will be applied."
  ADJSIZE=""
# See if source is target resolution in PAL
# If so, just rescale; aspect ratio should be fine
elif [[ $CURWIDTH == $TGTWIDTH && $CURHEIGHT == $PALHEIGHT ]];
then
  echo "Source appears to be PAL of target resolution ($TGTWIDTH x $PALHEIGHT)."
  echo "Assuming correct aspect ratio and rescaling."
  ADJSIZE="yuvscaler -O $FORMAT -v 0 -n n |"
elif [[ $ESTASPECT -ge $MINASPECT && $ESTASPECT -le $MAXASPECT ]];
then
  echo "Source is within 10% of target aspect ratio."
  echo "Assuming correct aspect ratio and rescaling."
  ADJSIZE="yuvscaler -O $FORMAT -v 0 -n n |"
# Otherwise, scale and/or pad with black bars
else
  echo "Scaling and/or padding with letterbox bars"
  # For non-DVD formats, widescreen needs to be padded to make
  # it fullscreen.
  [ $FORMAT != "DVD" ] && [ $ASPECT == "WIDE" ] && \
    ADJSIZE="yuvscaler -O $FORMAT -v 0 -n n -M WIDE2STD |"
  # Non-DVD standard sizes can be scaled directly
  [ $FORMAT != "DVD" ] && [ $ASPECT == "FULL" ] && \
    ADJSIZE="yuvscaler -O $FORMAT -v 0 -n n |"
  # DVD can be scaled directly
  [ $FORMAT == "DVD" ] && \
    ADJSIZE="yuvscaler -O $FORMAT -v 0 -n n |"
fi

echo "Creating and encoding video stream..."
mkfifo stream.yuv
mplayer -nosound -noframedrop -vo yuv4mpeg -vf pp=hb/vb/dr,hqdn3d "$INFILE" &
eval `echo "cat stream.yuv | $ADJUSTFPS $ADJSIZE nice -n 16 mpeg2enc $ASPECTFMT $VIDFMT $VIDFPS -v 0 -n n -H -o $OUTPREFIX.$SUF"`

echo "Creating WAV of audio stream..."
mplayer -vc dummy -vo null -ao pcm -aofile stream.wav "$INFILE"
# echo "Normalizing WAV audio..."
# normalize --amplitude=-14dBFS stream.wav
echo "Encoding WAV..."
cat stream.wav | mp2enc $SNDOPTS -o "$OUTPREFIX.mpa"

echo "Multiplexing audio and video together..."
tcmplex -i "$OUTPREFIX.$SUF" -p "$OUTPREFIX.mpa" -o "$OUTPREFIX.mpg" $MUXOPTS

echo "Cleaning up..."
rm stream.yuv
rm stream.wav
# rm "$OUTPREFIX.$SUF"
# rm "$OUTPREFIX.mpa"
rm fileinfo

echo "Done"
I had some problems with frame rate which I think are temporarily fixed, although messily. Encoding is fairly slow - for DVD encoding, about 4 frames per second on my Athlon XP 1600. VCD is faster, but still takes a good chunk of time. YMMV. I've included a 'nice' statement in the encoding command, so it should be possible to let it run in the background without much interference (though it'll still hog a lot of your disk activity).

There's an option for encoding VCD resolution in DVD format (the 'dvd-vcd' argument), which is supposed to allow something like 450 minutes of video on a DVD, but I have not tried using it yet.

This script is exclusively written to encode NTSC, so if you are going for PAL, you will need to make some modifications. Maybe I'll add PAL someday, but I have no use for it.

No guarantees of any kind are made regarding this script. Use at your own risk! Let me know if you find bugs or have suggestions for improvement. Also let me know if you try it and it works!

Update: Several improvements have been made. Some minor logic cleanup, and the addition of a fuzzy-logic bit that tries to guess whether the input is at the correct aspect ratio (to account for almost-correct aspect ratios or weird sizes). I've tested the script on a short clip for all output formats in full-frame mode. Seems to work OK.

Last edited by wapcaplet; 06-07-2004 at 11:02 PM.
 
Old 06-07-2004, 04:10 PM   #2
XavierP
Moderator
 
Registered: Nov 2002
Location: Kent, England
Distribution: Debian Testing
Posts: 19,192
Blog Entries: 4

Rep: Reputation: 475Reputation: 475Reputation: 475Reputation: 475Reputation: 475
Wapcaplet - your Success Story on encoding video seems to be ideal for our LinuxAnswers section.

Would you be willing to submit it? It would be of help to the site and to the rest of our membership if you would do so (it would also put your instructions in a prominent place for anyone searching for it ).

If you are willing to do so, read this link on submitting an Answer beforehand.

Thanks.
 
Old 08-01-2004, 03:14 AM   #3
Samual
LQ Newbie
 
Registered: Jul 2004
Posts: 1

Rep: Reputation: 0
use this for PAL

elif [[ $CURFPS == "25.000" ]];
then
echo "Source is 25 fps (PAL film). Encoding as PAL film."
ADJUSTFPS="yuvfps -s 24:1 -r 25:1 -v0 |"
VIDFPS="-F 3"
 
Old 08-01-2004, 01:03 PM   #4
wapcaplet
LQ Guru
 
Registered: Feb 2003
Location: Colorado Springs, CO
Distribution: Gentoo
Posts: 2,018

Original Poster
Rep: Reputation: 48
Quote:
use this for PAL
I think that would only encode to PAL if the source is PAL 25fps; ideally, PAL output would work regardless of what the input format is. It also gets a little tricky with anything involving widescreen, since a different amount of padding must be added for the various formats; PAL DVD is a different resolution than NTSC DVD, for instance, so I'd have to account for that. I will try to add PAL output support soon, though!

There is now a sourceforge project for my script and GUI:

http://tovid.sourceforge.net/

Keep an eye on that for further developments.

Last edited by wapcaplet; 08-01-2004 at 01:05 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Video tape to DVD - encoding problems pingu Linux - Software 3 01-11-2007 03:01 AM
DISCUSSION: Converting video to VCD, SVCD, or DVD wapcaplet LinuxAnswers Discussion 665 12-29-2005 02:02 AM
burn VCD from various video format? macarthor Linux - Software 11 10-26-2004 09:59 AM
tovid DVD/VCD video converter GUI wapcaplet LinuxQuestions.org Member Success Stories 2 07-06-2004 02:27 PM
Encoding divx to vcd using mencvcd or transcode or divx2vcd... GnomeKing Linux - Software 5 06-23-2003 01:44 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General > LinuxQuestions.org Member Success Stories

All times are GMT -5. The time now is 11:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration