Archiving Recordings to DVD

From MythTV Official Wiki
Jump to: navigation, search

Clean.png Cleanup: This article or section may require cleanup. Discuss the issue on the talk page

The easiest way to archive recordings and/or videos to DVD is to use MythArchive

Alternatively, either simply write off the videos as data to a writable medium or author a 'proper' DVD that plays in real DVD players.

There's also a page of External Links

This article describes the second approach and uses the following basic steps:

  1. Find the file you want.
  2. Run avidemux2 and break the file into video and audio portions.
  3. Run mplex to reassemble it in DVD compatible format.
  4. Run dvdauthor to create a DVD compatible file structure.
  5. Run growisofs to actually make the DVD.

Find the File

The files are saved with a long numeric file name that has to do with the start and stop times of the recording and are not at all intuitive. There are scripts to make links to the files with human readable file names - one such is mythname.pl in the contrib directory.

Burning .nuv Files to DVD

Important.png Note: This is specific to MPEG-2 .nuv files created by Hauppauge PVR-x50 video capture cards.

The software packages you will want are:

  • dvd+rw-tools
  • dvdauthor
  • mjpegtools
  • avidemux2
  • transcode - not necessary for this, but useful for working with video
  • k3b - a gui for burning DVD's and CD's. Not necessary, but useful.

The recipe:

1. Find the file you want.

2. Run avidemux2 and open the .nuv file that is the program you want to burn to DVD.

3. You will now cut out the segments you want. Find the beginning of the segment to cut.

  • Click the "Previous keyframe" button (<<) to make sure your cut is on keyframe.
  • Click twice on "A" when you are at the beginning of the segment you want to save.
  • Then find the end of the segment, click "Next keyframe" (>>) and click "B".
  • Note: If you do not cut on keyframes, you may have audio sync problems.

4. Then save the raw video stream and audio.

  • Set "Outp.fmt" to "Mpeg video".
  • Then go to File-> Save -> Save Raw Video Stream.
  • Save the file as "1.m2v".
  • When that's done, go to Audio -> Save Audio.
  • Save the file as "1.mp2".

5. Repeat steps 2, 3, and 4 until you have all segments you want saved.

6. Mplex the video and audio for each segment together in DVD-MPEG2 format. Do that by running

mplex -f 8 -o 1.mpg 1.m2v 1.mp2

7. Create a DVD file system by running

dvdauthor -o DVD 1.mpg 2.mpg ... 
dvdauthor -T -o DVD

8. Put a blank DVD in your drive and write the video by running

growisofs -Z /dev/scd0 -dvd-video DVD

or you can create an image if you want to make multiple copies:

mkisofs -dvd-video -o dvd.img DVD

9. Be sure and check the DVD in a player and then delete all the files you created in this process.

Notes:

You can reduce the size of your files and fit more video on a DVD by using tcrequant, which is part of transcode. Do this as shown

tcrequant -i 1.m2v -o 1-rq.m2v -f 1.5

The 1.5 is the reduction factor. You can adjust this to be any value between 1 and 2. 1 would keep the file the same size (wouldn't make any sense to do so), and as far as I understand it, 2 would reduce the video file size by half. For DVD5 you can calculate the requantize factor with this formula:

requant_factor = (video_size / (4700000000 - audio_size)) * 1.04

Where audio_size is the size of all audio and subtitle streams in bits.


Important.png Note: The constant above (4700000000) assumes single-layer DVD media. If using dual-layer DVD media, double the number.

The steps above create a DVD that starts playing the video automatically. If you want to burn a DVD with menus and multiple video titles, see the DVDs With Menus How-To.

Burning HDTV .nuv Files to DVD

  • avidemux 2.0.42 is known to work. (Earlier versions may not.)
  • List of other dependencies here.

The following recipe has been used to archive 720p HDTV .nuv files to DVD:

1. Find the file you want.

2. Run avidemux2 and open the .nuv file that is the program you want to burn to DVD.

3. Find the beginning of the segment to cut.

  • Click the "Previous keyframe" button (<<) to make sure your cut is on a keyframe.
  • Click twice on "A" when you are at the beginning of the segment you want to save.
  • Then find the end of the segment, click "Next keyframe" (>>) and click "B".

4. Select "DVD" for the video type and "FFm AC3" for the audio type.

5. Set "Outp.fmt" to "Mpeg A+V (PS)".

6. Click "V Filter" to add video filters to create an output stream that is appropriate for DVD as follows.

7. The first filter should be to "Resample FPS" to 29.97. (I said no to "Use linear blend?")

8. The second filter should be to "Crop" enough lines off the top to remove the VBI data. (4 lines works for me.)

9. The third and final filter should be "Mplayer Resize" to 720x480.

10. Select "V Process" so the video actually gets processed.

11. Select "A Filter" to add an audio filter in order to sync the audio and video streams.

12. Select "Timeshift" and add the necessary shift in milliseconds. (This should be the amount displayed when the file was indexed as you loaded it into avidemux.)

13. Select "A Process" so the audio actually gets processed.

14. Save the file to 1.mpg.

15. Create a DVD file system by running

dvdauthor -o DVD 1.mpg
dvdauthor -T -o DVD 

16. Put a blank DVD in your drive and write the video by running

growisofs -Z /dev/scd0 -dvd-video DVD

17. Be sure and check the DVD in a player and then delete all the files you created in this process.


Important.png Note: This has been tested on 720p (1280x720) capture of PBS programming where no commercials need to be removed and thus the show only needs to be trimmed at the ends.

Archive to VCD

Cory said:

I've been relatively frustrated with the experience, myself... but I did manage to make one SVCD go using the following steps:

1. strip the audio

mpeg2desc -a0 < infile.nuv > temp.mp2

2. strip the video

mpeg2desc -v0 < infile.nuv > temp.m2v

3. resize the video (by 1.5x e.g.)

tcrequant -i temp.m2v -o temp_crunched.m2v -f 1.5

4. resample audio for 44.1kHz SVCD-compliant mp2

mpg123 -s temp.mp2 | sox -c 2 -s -r 48000 -w -t raw - -r 44100 -t wav - | \
mp2enc -b 192 -r 44100 -o temp44.mp2

5. recombine into SVCD-friendly stream

tcmplex -N -m s -p temp44.mp2 -i temp_crunched.m2v -o temp.mpg

6. Cut out commercials with GOPchop

gopchop... plus gui-isms -> temp_cut.mpg

7. master SVCD image

vcdimager -t svcd temp_cut.mpg

8. burn image

cdrdao write --device 0,6,0 videocd.cue

Boy... I forgot what a royal PITA this was! It did, however, result in a 695MB standards-compliant SVCD with 43 minutes of video with SP-VHS quality.

Doing the GOPchop after the requantization was necessary, as it currently appears to break the audio streams so stream strippers don't recognize them.

Haven't gone down the DVD road yet. Right now I'm thinking of trying to modify the procedure to make a 'mini-DVD' (e.g. DVD format on a CD), using 1/2 D1 size of 352x480. That should be easily scalable to full-sized DVD's, and probably just about as compatible with set-top DVD players. So far my experience with SVCD compatibility has been underwhelming.


stan submitted this script:

Script.png write_dvd.sh
#!/bin/sh

##################################################################
#
# write_dvd
#
# Writes a DVD from a MythTV saved .nuv file (assumeing it was saved
# with a PVR-250 or PVR-350, thus it's already in MPEG2 format)
#
# Argument 1 is the name of the .nuv file
#
################################################################

WORKDIR=work$$

cd /cache/tmp

mkfifo aud0
mkfifo vid0
mkfifo dvdmpg

# If getting mplex errors with DVB recs, try adding -s to mpeg2desc
mpeg2desc -a0 < $1 > aud0 &
mpeg2desc -v0 < $1 > vid0 &
mplex -f 8 -V -o dvdmpg aud0 vid0 &
dvdauthor -o $WORKDIR -f dvdmpg
dvdauthor -o $WORKDIR -T

rm aud0
rm vid0
rm dvdmpg

growisofs -dvd-video -Z /dev/dvd $WORKDIR

rm -r $WORKDIR

Tero Tilus:

I had to add -s (skip to first valid header) to mpeg2desc options in the previous wrie_dvd -script.  Otherwise mplex would not read the audio fifo.  I don't exactly know the the reason why I needed this.  It propably has something to do with the fact that I record using budget dvb card.  AFAIK MythTV just writes the mpeg stream coming from cable to disc.

david blevins said:

Here is a perl script I cooked up that makes a directory for each title.  It's kind of a hack, but does the trick.
Script.png some_hack.sh
#!/usr/bin/perl -w

# Where your recordings sit
$RECDIR='/var/lib/mythtv/';
$LINKDIR='/media/tv/';

# Command to return the sql rows. Must have -N !!A
$MYSQL="mysql -N -u root mythconverg";
$SQL="select chanid, starttime, endtime, title, subtitle from recorded order by starttime";

$data=`echo $SQL | $MYSQL`;

@rows = split('\n',$data);
foreach (@rows){
    s/[[;]]/ -/g;
    s/[\'\`,.]//g;

    ($chanid, $starttime, $endtime, $title, $subtitle)=split('\t',$_);

    $subtitle='unknown' unless ($subtitle);

    $REALFILE="${RECDIR}${chanid}_${starttime}_${endtime}.nuv";
    $FAKEFILE="${LINKDIR}${title}/${subtitle}_${starttime}.mpg";
    print $FAKEFILE . "\n";
    `mkdir '${LINKDIR}${title}' 2>/dev/null`;
    `ln -s '$REALFILE' '$FAKEFILE'`;

}

Michael Joyner wrote: The above script doesn't work on my system. I had to change it to as follows:


Script.png another_hack.sh
#!/usr/bin/perl -w

# Where your recordings sit
$RECDIR='/home/myth/recordings/';
$LINKDIR='/home/mjoyner/DVD/';

# Command to return the sql rows. Must have -N !!A
$MYSQL="mysql -N -u root mythconverg";
$SQL="select chanid, starttime, endtime, title, subtitle from recorded order by starttime";

$data=`echo $SQL | $MYSQL`;

@rows = split('\n',$data);
foreach (@rows){
    s/[[;]]//g;
    s/[\'\`,.]//g;
    s/[-]//g;
    s/[ ]//g;

    ($chanid, $starttime, $endtime, $title, $subtitle)=split('\t',$_);

    $subtitle='unknown' unless ($subtitle);

    $REALFILE="${RECDIR}${chanid}_${starttime}_${endtime}.nuv";
    $FAKEFILE="${LINKDIR}${title}/${subtitle}_${starttime}.mpg";
    print $FAKEFILE . "\n";
    `mkdir '${LINKDIR}${title}' 2>/dev/null`;
    `ln -s '$REALFILE' '$FAKEFILE'`;

}

The above script modified to support specific day (as requested in q&a) and wiping the destination directory (commented out for safety atm), tidied up a little, and removed the depreciated mysql -N. - Paul Lakin

Application-x-perl.png test.pl
#!/usr/bin/perl -w

## Usage

# test.pl [date]
# where date is an optional string. (See 'man date')
# e.g.
#  test.pl
#  test.pl yesterday
#  test.pl -1day
#  test.pl 2005/07/25



## Paths

# Directories
$RECDIR = '/var/video/recordings';
$LINKDIR = '/var/video/dvd';

# Binaries
$MYSQLBIN = '/usr/bin/mysql';



## Code

# Add while statement if date is specified
my $datewhile = '';
if ($ARGV[0]) {
  $datestart = `date -d '$ARGV[0] 00:00:00' +'%Y-%m-%d %H:%M:%S'`;
  $dateend = `date -d '$ARGV[0] 23:59:59' +'%Y-%m-%d %H:%M:%S'`;
  $datestart =~ s/[\n]//g;
  $dateend =~ s/[\n]//g;
  if ($datestart && $dateend) {
    $datewhile = "WHERE starttime > '$datestart' AND starttime < '$dateend'";
  }
}

# Command to return the sql rows. Must have --skip-column-names.
$mysql = "$MYSQLBIN --skip-column-names --user=mythtv --password=mythtv  mythconverg";
$sql = "SELECT chanid, starttime, endtime, title, subtitle
        FROM recorded $datewhile ORDER BY starttime";

@data = `echo \"$sql\" | $mysql`;

# Uncomment to rm the contents of the LINKDIR.
# (Make sure your paths are correct, and if possible run as non-root.)
#`rm -r $LINKDIR/`;

foreach (@data) {
    s/[[;\'\`,.\-\n]]//g;

    ($chanid, $starttime, $endtime, $title, $subtitle)=split('\t',$_);

    $starttime =~ s/\s//g;
    $endtime =~ s/\s//g;
    $chanid =~ s/\s//g;

    $subtitle='unknown' unless ($subtitle);

    $REALFILE="${RECDIR}/${chanid}_${starttime}_${endtime}.nuv";
    $FAKEFILE="${LINKDIR}/${title}/${subtitle}_${starttime}.mpg";
    print $REALFILE . " -> " . $FAKEFILE . "\n";
    `mkdir -p '${LINKDIR}/${title}' 2>/dev/null`;
    `ln -s '$REALFILE' '$FAKEFILE'`;
}

Updated Scripts from Arne Flones

I've worked on the above scripts so they work a bit better and offer more flexibility.

First, is the Perl script which builds symlinks to the MythTV recordings. I've changed the script so that it actually works properly (with my version of MythTV--mythtv-0.18.1-r1 on Gentoo). In particular, it formats the file name correctly, stripping newlines and other formatting garbage. It also checks for file existence and outputs a message if it does not. It removes all previous links, if they exist so one can crontab it if one wishes. It doesn't print all the useless stuff while it works.

N.B., I have not tested the date parameter stuff. Somebody else can do that as I have no interest in that feature.

I've named the script "mythlink":

Script.png test.pl
#!/usr/bin/perl -w

## Usage
# test.pl [date]
# where date is an optional string. (See 'man date')
# e.g.
#  mythlink
#  mythlink yesterday
#  mythlink -1day
#  mythlink 2005/07/25

## Paths

# Directories
# Adjust these per your Myth Installation
$RECDIR = '/var/video';  # where your nuv files reside
$LINKDIR = '/home/user/media/mythtv';   # where you want your symlinks

# Binaries
$MYSQLBIN = '/usr/bin/mysql';

## Code  -- Don't know if this actually works
# Add while statement if date is specified
my $datewhile = '';
if ($ARGV[0]) {
    $datestart = `date -d '$ARGV[0] 00:00:00' +'%Y-%m-%d %H:%M:%S'`;
    $dateend = `date -d '$ARGV[0] 23:59:59' +'%Y-%m-%d %H:%M:%S'`;
    $datestart =~ s/[\n]//g;
    $dateend =~ s/[\n]//g;
    if ($datestart && $dateend) {
        $datewhile = "WHERE starttime > '$datestart' AND starttime < '$dateend'";
    }
}

# Command to return the sql rows. Must have --skip-column-names.
$mysql = "$MYSQLBIN --skip-column-names --user=mythtv --password=mythtv  mythconverg";
$sql = "SELECT chanid, starttime, endtime, title, subtitle
        FROM recorded $datewhile ORDER BY starttime";

@data = `echo \"$sql\" | $mysql`;

# Uncomment to rm the contents of the LINKDIR.
# (Make sure your paths are correct, and if possible run as non-root.)
# Script isn't very useful unless we do this
`rm -r $LINKDIR/`;

foreach (@data) {
    s/[[;\'\`,.\-\n]]//g;

    ($chanid, $starttime, $endtime, $title, $subtitle)=split('\t',$_);

    $starttime =~ s/\s//g;
    $starttime =~ s/\W//g;
    $endtime =~ s/\s//g;
    $endtime =~ s/\W//g;
    $chanid =~ s/\s//g;
    $subtitle =~ s/\n//g;
    $title =~ s/\W//g;
    $subtitle =~ s/\W//g;
    $subtitle='unknown' unless ($subtitle);

    $REALFILE="${RECDIR}/${chanid}_${starttime}_${endtime}.nuv";
    $FAKEFILE="${LINKDIR}/${title}/${subtitle}_${starttime}.mpg";
    if (-f $REALFILE) {
        `mkdir -p '${LINKDIR}/${title}' 2>/dev/null`;
        `ln -s '$REALFILE' '$FAKEFILE'`;
    }
    else {
        print "File: |$REALFILE| does not exist.\n";
        print "   Title: $title\n";
        print "   Subtitle: $subtitle\n";
    }
#    print $REALFILE . " -> " . $FAKEFILE . "\n";  # shut up
}

Here's a small diff that makes this script work with mythtv 0.20 and even if you don't use .nuv files.

37c37
< $sql = "SELECT chanid, starttime, endtime, title, subtitle
---
> $sql = "SELECT chanid, starttime, endtime, title, subtitle, basename
50c50
<     ($chanid, $starttime, $endtime, $title, $subtitle)=split('\t',$_);
---
>     ($chanid, $starttime, $endtime, $title, $subtitle, $basename)=split('\t',$_);
57a58
>     $basename =~ s/\n//g;
62c63
<     $REALFILE="${RECDIR}/${chanid}_${starttime}_${endtime}.nuv";
---
>     $REALFILE="${RECDIR}/${basename}";

The second script builds the DVD image and optionally burns it to the media. I've modified this script so that it takes command line switches for a couple nice features, gives a "usage" and validates the input file. Also, if you give it a symbolic link as input paramter (like those built by the "mythlink' Perl script) it converts it to the actual NUV file since the DVD tools used here don't seem to like symlinks.

I've named this BASH script "nuv2dvd". See "usage" within the script.

Script.png nuv2dvd.sh
#!/bin/sh

function usage {
    echo >&2
    echo 'nuv2dvd - build a DVD image from a MythTV nuv file' >&2
    echo "ERROR - $1" >&2
    echo >&2
    echo 'usage: nuv2dvd [-b] [-k] [-o] <nuv-file> [image-dir]'  >&2
    echo 'where:' >&2
    echo '   nuv-file  Input file - presumes MPEG2 format.' >&2
    echo '             Default: none, required parameter.' >&2
    echo >&2
    echo '   image-dir Directory name for DVD image.' >&2
    echo '             Presumes keep' >&2
    echo '             Default: nuv2dvd####' >&2
    echo >&2
    echo 'flags:' >&2
    echo '   b         Burn image to DVD' >&2
    echo '             Default: do not burn.' >&2
    echo >&2
    echo '   k         Keep image directory' >&2
    echo '             Default: if burning, do not keep.' >&2
    echo >&2
    echo '   o         Overwrite existing image' >&2
    echo '             Default: do not overwrite.' >&2
    echo >&2
}

# Set the following to your temporary directory.
tmpdir="/tmp"

burn=0
keep=0
ovrwrt=0

while getopts bko opt
do
    case "$opt" in
        b)  burn=1;;
        k)  keep=1;;
        o)  ovrwrt=1;;
        /?) usage "Unknown option"
                exit 1;;
    esac
done
shift `expr $OPTIND - 1`

if [ $# -lt 1 ]
then
    usage "Missing input file, <nuv-file>"
    exit 1
fi

# Check for number of parameters
if [ $# -eq 1 ]
then
    # default image directory
    imgdir=nuv2dvd$$
else
    imgdir=$2
    keep=1  # if user specifies, keep it
fi

nuvfile=$1

if [ -L ${nuvfile} ]
then
    # Make sym link be actual file
    mynuv=`ls -l ${nuvfile}`
    nuvfile="${mynuv##*-> }"
fi

if [ ! -r "${nuvfile}" ]
then
    usage "NUV file is not readable - ${nuvfile}"
    exit 1
fi

if [ -d "${imgdir}" ]
then
    if [ ${ovrwrt} -eq 0 ]
    then
        usage "image directory exists, overwrite not enabled - ${imgdir}"
        exit 1
    else
        # Clear existing directory for overwrite
        rm -fr ${imgdir}
    fi
fi

cd ${tmpdir}
echo "Building DVD image at ${tmpdir}/${imgdir}"

mkfifo aud0
mkfifo vid0
mkfifo dvdmpg

# if getting mplex errors with DVB recs, try adding -s to mpeg2desc
mpeg2desc -a0 < ${nuvfile} > aud0 &
mpeg2desc -v0 < ${nuvfile} > vid0 &
mplex -f 8 -V -o dvdmpg aud0 vid0 &
dvdauthor -o ${imgdir} -f dvdmpg
dvdauthor -o ${imgdir} -T

rm aud0
rm vid0
rm dvdmpg

# and burn it on a DVD, if desired
if [ ${burn} -eq 1 ]
then
    echo
    echo "Burning image to DVD"
    growisofs -Z /dev/dvd -dvd-video ${imgdir}
    if [ ${keep} -eq 0 ]
    then
        echo
        echo "Removing ${imgdir}"
        rm -r ${imgdir}
    fi
fi
echo
echo "Finished."
if [ ${keep} -eq 1 ]
then
    echo "DVD image is at ${tmpdir}/${imgdir}"
fi

Questions and Answers

Q: Is some of this PVR-X50 / DVB specific?
A: See the DVD Section


Q: What about nuvexport?
A: nuvexport took me about 24 hours to produce a DivX. The "wrie_dvd" script above took about 5 minutes to burn a DVD, so now I will use that. - jd
A2: Actually nuvexport is not that slow when generating MPEG-4 like DivX and Xvid. It takes me around one hour on my 1.8 GHz PC, while it takes much longer to generate MPEG2 compatible formats with nuvexport. Nuvexport can be used to extract the .nuv/.mpg files with SQL statements, so that the recordings can be inserted in the database again. This is the fastest way of archiving recordings. Note that .nuv files can be played directly from a DVD even on Windows if the dsmyth filter is used.


Q: Should we split up into DVD and (S)VCD burning?
A: It's mostly the same so probably not needed. - Henk Poley


Q: Having tried the "wrie_dvd" script above, I had audio sync issues with the authored DVD. (Rather noticable with people talking). From reading the mailing list, I have read that mpeg2desc -m < inputfile will reveal the audio offset and that can be corrected by using -O option followed by the result of the mpeg2desc -m call above followed by the text mpt,i.e.

mplex -f 8 -V -O 3016mpt ....   

Is this required for all users or it is something that is based on my video source. I am using PVR250 for captures.
A:


Q: You could use the integrated MythTVBurn scripts and web interface?
A: Why isn't MythTVBurn being developed? MythTVBurn (available from SourceForge) is an amazing plugin to the Mythfrontend that lets you build and burn a DVD using your remote. Unfortunately, the author is no longer supporting its development and as far as I can tell there is no comparable subsitution for MythTV. MythTV rocks but REALLY needs this simple addition, because it's a fundamental use of the VCR: so MythTV can burn a DVD, just like VCRs tape onto VHS tapes!!! Otherwise there is no simple way to watch a recording on any machine other than the MythTV box, and not even on that box if you eventually run out of HD space. Any ideas? The "wrie_dvd" script above works beautifully, but few ppl prefer using a shell script to the remote.

A2: MythTVBurn works, sort of. There are some minor problems with the scene menus being flipped upside down, but there is at least one patch floating around to correct that. I managed to get it working on the latest 18.x Knoppmyth after a couple of hours. Well, it would generate valid ISO images, it still doesn't detect the DVD burner correctly but I work around that by transferring the images to another machine for burning. I also had issues with low bitrate PVR250 recordings that played fine on Myth, but stuttered every few seconds when transcoded to DVD. This was fixed by changing the recordings to a high bitrate. There are still problems, but it seems to work most of the time now. With a little bit of work, I think MythTVBurn is the way to go. It needs one more release with the minor problems fixed and it would work quite well for most people. A simple option in the web menu to display generated ISO files(with a useful name), let you download them for burning and delete them would make this a 1.0 release. The next step would be to have it do some transcoding to delete commercials with as low a quality loss as possible, and fix the DVD recorder section. After that, a wishlist would be a settings config to customize the background menu and music, and a native Mythtv module so you wouldn't need mythweb.

Would the author of the above note please stand up? If you have a patched version, I'm sure I'm not the only one who would like to grab it.  :-) --Bay Link

Q: Is there any preference for which media to use? DVD+ or DVD-? Most burners can do both nowadays; do standalone players work better with one or the other?
A: Each standalone player has specific capabilities, just like the burners. Some can read CDRW, DVD+R, DVD-R, MP3 CD's, etc., but you will need to refer to the specs for that particular player in order to determine which media it can read. I once heard that -R is more commonly supported in standalone players, but these days most media are probably supported by most players.

A2: Older players, if they support recorded DVD material at all, will usually recognize DVD-R. This seems to vary by the manufacturer of the medium, the strength of the laser and optical pickup sensitivity of the DVD player, etc. If you have problems with an older player, your probaly better off just getting a new one.


Q: How to change the sql statement in the script submitted by David Blevins so you can run it for only a specified period of time: i.e. the day before yesterday. I've never used perl and therefor don't know how to put this in the script.
A: See just added version of script. - Paul Lakin