User:Misterhaan/Nuvexport Tweaks

From auWiki
Jump to navigation Jump to search

i use nuvexport to compress and downsample my recordings from mythtv, partly to save space and partly so my xbox can play them on xbox media center. it doesn’t quite do everything i need it to though, but since it’s all perl i can change that! on my fedora installation, nuvexport is found in [code]/usr/share/nuvexport/[/code] and is owned by root. i copy the entire directory into my user’s home directory, make my changes there using my favorite text editor, then copy the changed files back.

allow larger crop to deal with 4:3 shows pillarboxed for 16:9 broadcast

i’m not sure why, but nuvexport limits top and bottom cropping to 20% and left and right crop to only 5%. this is fine if you’re trying to take 12.5% off the top and bottom to de-letterbox 16:9 content that was broadcast as 4:3, but it won’t let you take 12.5% off the sides to de-pillarbox 4:3 content that was broadcast as 16:9. the code that does the limiting is on line 178 of [code]export/generic.pm[/code]:

[code]my $max = ($side eq 'top' || $side eq 'bottom') ? 20 : 5; my $pct = query_text("Crop broadcast overscan $side border (0-5\%) ?",

                    'float',
                    $self->val("crop_$side"));[/code]

i also include the next line because it shows a prompt saying 0-5% even though sometimes it’s 20% — we’ll fix that too. replace those lines with these:

[code]my $max = 20; my $pct = query_text("Crop broadcast overscan $side border (0-$max\%) ?",

                    'float',
                    $self->val("crop_$side"));[/code]

it actually makes the code simpler by doing the same thing for every side.

limit framerate to 24

my xbox can’t keep up with the high framerates hdtv can be broadcast in (sometimes around 60), so i have mencoder drop it down to the framerate used by the ntsc standard. if you’re curious what ntsc is, it’s the sd tv standard used in north america and japan. this gets added as a video filter in [code]export/mencoder.pm[/code]. first find the line with “# Add any additional settings from the child module.” add these three lines just before it:

[code] if ($episode->{'finfo'}{'fps'} >= 59) {

           $mencoder .= " -vf decimate=2:1000:1600:.001 -ofps 24000/1001";
       }[/code]

it may work to change the >= 59 to a smaller number, but i can’t find what that decimate filter does so it may cause problems for video at 30 fps. also 30 fps is probably within the xbox’s capabilities.

note that since this change is in mencoder.pm it won’t apply if you use ffmpeg instead.

keep surround sound

nuvexport downmuxes surround sound to stereo, which is a shame if you have digital audio going into a 5.1 receiver like i do. this is the most complicated modification i’ve made to nuvexport so far since it’s actually adding another option for audio codec. the values supported for this option are mp3 (default), ac3, and copy. due to limitations in mythtranscode, the program that gives us just the parts of the video that aren’t commercials, nuvexport actually starts with stereo if you have [code]use_cutlist = yes[/code], so you need to set it to no for ac3 or copy. i think they actually patched mythtranscode but that didn’t seem to make it into nuvexport — maybe i’ll figure that one out eventually. the changes here happen in [code]export/mencoder/XviD.pm[/code]:

find the line that says “# Load the following extra parameters from the commandline” and insert this line just before the Audio bitrate line that’s a couple lines down from there (line 22):

[code] add_arg('a_codec:s', 'Audio codec (mp3, ac3, or copy)');[/code]

next fine “# Audio Bitrate” (line 86). you’ll need to replace that section to add the audio codec option and skip the bitrate option if the codec is copy (because then we don’t set the bitrate). here’s what the section of the file should look like before the edit:

[code] # Audio Bitrate

       $self->{'a_bitrate'} = query_text('Audio bitrate?',
                                         'int',
                                         $self->val('a_bitrate'));[/code]

change it to this:

[code] # Audio Codec *misterhaan+3

       $self->{'a_codec'} = query_text('Audio codec (mp3, ac3, or copy)?',
                                       'string',
                                       $self->val('a_codec'));
   # Audio Bitrate
       if ($self->{'a_codec'} ne 'copy') {
           $self->{'a_bitrate'} = query_text('Audio bitrate?',
                                             'int',
                                             $self->val('a_bitrate'));
       }[/code]

those changes got it to read in the audio codec, so now we need to make sure it respects it. toward the end of the file (line 156) find “# Second pass” — we’ll need to split out the part currently telling it to use mp3 and check which audio codec is configured and use the right one. here’s what this section looks like before the edit:

[code] # Second pass

           print "Final pass...\n";
           $self->{'mencoder_xtra'} = " $params"
                                      ." -oac mp3lame -lameopts vbr=3:br=$self->{'a_bitrate'}"
                                      ." -passlogfile /tmp/xvid.$$.log"
                                      ." -xvidencopts bitrate=$self->{'v_bitrate'}:pass=2:quant_type=mpeg:threads=2:keyframe_boost=10:kfthreshold=1:kfreduction=20 ";[/code]

change it to this:

[code] # Second pass

           print "Final pass...\n";
           $self->{'mencoder_xtra'} = " $params";
           if ($self->{'a_codec'} eq 'copy') {
               $self->{'mencoder_xtra'} .= " -channels 6 -oac copy";
           } elsif ($self->{'a_codec'} eq 'ac3') {
               $self->{'mencoder_xtra'} .= " -channels 6 -oac lavc -lavcopts acodec=ac3:abitrate=$self->{'a_bitrate'}";
           } else {  # mp3 is default
               $self->{'mencoder_xtra'} .= " -oac mp3lame -lameopts vbr=3:br=$self->{'a_bitrate'}";
           }
           $self->{'mencoder_xtra'} .= " -passlogfile /tmp/xvid.$$.log"
                                      ." -xvidencopts bitrate=$self->{'v_bitrate'}:pass=2:quant_type=mpeg:threads=2:keyframe_boost=10:kfthreshold=1:kfreduction=20 ";[/code]

that handled two-pass encoding which i don’t actually use, so we need to make sure to handle single pass in a similar way. the “# Single pass” section is just below second pass and looks like this before the edit:

[code] # Single pass

       else {
           $self->{'mencoder_xtra'} = " $params"
                                      ." -oac mp3lame -lameopts vbr=3:br=$self->{'a_bitrate'}";[/code]

change it to this:

[code] # Single pass

       else {
           $self->{'mencoder_xtra'} = " $params";  # a_codec support *misterhaan+7 (one line replaced)
           if ($self->{'a_codec'} eq 'copy') {
               $self->{'mencoder_xtra'} .= " -channels 6 -oac copy";
           } elsif ($self->{'a_codec'} eq 'ac3') {
               $self->{'mencoder_xtra'} .= " -channels 6 -oac lavc -lavcopts acodec=ac3:abitrate=$self->{'a_bitrate'}";
           } else {  # mp3 is default
               $self->{'mencoder_xtra'} .= " -oac mp3lame -lameopts vbr=3:br=$self->{'a_bitrate'}";
           }[/code]

if you use nuvexportrc to set default values, you can now specify a_codec = copy to leave the audio stream untouched. if you run nuvexport interactively, you will get an addition prompt asking which codec you want to use for audio.


support running as a user job

nuvexport tries to detect your terminal, which doesn’t work when running as a mythtv user job. it’s only doing it to get a way to clear the screen, but we can just use the clear command for that. first, remove the terminal code from [code]nuv_export/shared_utils.pm[/code] (line 52):

[code]# Set up the terminal commands we need to send a clear-screen character

   use Term::Cap;
   my $OSPEED = 9600;
   eval {
       require POSIX;
       my $termios = POSIX::Termios->new();
       $termios->getattr;
       $OSPEED = $termios->getospeed;
   };
   our $terminal = Term::Cap->Tgetent({OSPEED=>$OSPEED});[/code]

now find the one spot that referenced the terminal and replace it with the clear command. here’s how it start out (line 94):

[code]# Clear the screen

   sub clear {
       print $DEBUG ? "\n" : $terminal->Tputs('cl');
   }[/code]

change it to this:

[code]# Clear the screen

   sub clear {
       print $DEBUG ? "\n" : `clear`;
   }[/code]