
"Roll Your Own GFA BASIC Program 8" by Troy H. Cheek on Jun 01, 2009
Once again, this week's article will only make sense if you started back at part 1.)
The actual code to call the conversion utilities is all pretty similar, so I've chosen as an example the most complicated one. In this example, EZMedia has determined that the video in question was created with my Plextor ConvertX TV tuner. Video created by this device almost never converts properly with HandBrake, so first we have to "massage" it with FFmpeg.
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " ";
Print # 2; "Calling FFmpeg"
Close # 2
c$ = "E:\Sage Stuff\MediaShrink\mediaEngineBins\ffmpeg\ffmpeg.exe "
c$ = c$ + "-i " + OriginalFilename$ + " "
c$ = c$ + "-vcodec copy -acodec copy "
c$ = c$ + TmpFilename$
System c$, Wait, Show SW_HIDE
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " ";
Print # 2; "FFmpeg exits."
Close # 2
It was at this point that I realized I was using more code to log my actions than I was to actually do anything useful, but given the number of times the program seemed to freak out rather than generating the expected output, it's worth it.
The GFA Basic System command allows you to run another program. To do this, you have to give it a command line which is almost exactly what you'd type at a Windows command prompt. In this case, the location of the executable followed by the options for that executable.
ffmpeg.exe is the executable I'm using. I tell it the input file, the video and audio options, and the output file. In this case, I'm inputting the original MPEG-2 video file and outputting to a temporary MPEG-2 video file in another directory. For the video and audo options, I'm telling ffmpeg to use the same options as present in the original file.
In theory, the output file should be identical to the input file. After all, I'm "converting" MPEG-2 to MPEG-2 using the exact same video and audio settings. Given the speed at which this command executes, ffmpeg is certainly not uncompressing and recompressing the video, just copying it. And yet the resulting file is about 5% smaller and, most importantly, doesn't cause HandBrake to choke.
The Wait command tells GFA BASIC to wait until ffmpeg finishes before continuing on with the program. Show SW_HIDE tells GFA to suppress the window that ffmpeg runs in. I've also used Show SW_MINIMIZE which opens the window but then minimizes it to the task bar. When I do that, I can unminimize the window to see what ffmpeg is doing. However, ffmpeg has been so reliable and runs so quickly that I eventually stopped doing that and just let the window be hidden.
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " ";
Print # 2; "Calling Handbrake ";
c$ = "E:\Sage Stuff\MediaShrink\mediaEngineBins\Handbrake
9.3\HandBrakeCLI.exe "
c$ = c$ + "-i " + TmpFilename$ + " "
c$ = c$ + "-o " + TmpAVIname$ + " "
c$ = c$ + "-f avi "
c$ = c$ + "-e xvid -b 2048 "
c$ = c$ + "--crop " + Str$(MaxY%) + ":" + Str$(MaxY%) + ":" +
Str$(MaxX%) + ":" + Str$(MaxX%)
Print # 2; "(crop"; MaxY%; "/"; MaxX%; ")"
Close # 2
System c$, Wait, Show SW_MINIMIZE
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " HandBrake exits."
Close # 2
Like ffmpeg, HandBrake is a video file convertor. In my very limited experience, it's a bit faster and produces better results that ffmpeg. However, HandBrake does choke on some of my files, hence the need to massage them with ffmpeg first.
As with ffmpeg, I create a command line specifying the input and output files along with video bitrate (using the default audio bitrate) and crop settings. HandBrake can detect margins and crop automatically, but I find the settings gleaned from the Comskip log files to be more accurate.
As HandBrake can take a couple of hours to convert a long movie, I generally just minimize its window instead of completely hiding it, though I change this all the time.
Rem kill temp files, kill original file
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " Kill old file, copy new one."
Close # 2
If Exist(TmpFilename$)
Kill TmpFilename$
EndIf
Kill OriginalFilename$
MoveFile TmpAVIname$ To NewFilename$
Assuming everything converted properly (not show are several checks to make sure that is so), it's now time to finish up. If there is a temporary MPEG video file, like that created by ffmpeg, it needs to be deleted now. Likewise, since we're sure we no longer needs the original video file, it gets deleted as well. Finally, we move the new AVI file from its temporary directory to its final home. With any luck, SageTV will now notice that the old MPEG file is gone and look for it, finding the new AVI file and deciding that it's the same file just renamed.
Without luck, SageTV deletes the new file, sticks it in the imported video list, or just ignores it entirely. This seldom happens, especially since I made sure the kill the original and put the new one in place immediately afterwards. The only way to make sure that SageTV always picks up the new file is to stop the SageTV service entirely while the change is being made. I can't do this from within GFA Basic, and it has the side effect of ruining whatever recording might be going on at the same time, so I just take my chances.
Open EZMFilename$ for Append As # 2
Print # 2; Time$; " Fimished!"
Close # 2
CloseW # 1
End
The CloseW (close window) command is probably not needed, seeing as End will close all the open windows anyway, but it never hurts to be neat.
The last bit of logging there is not a typo. At least, not an accidental one. Before getting really strict about the logging, the program was full of "finished!" statements here and there after just about every action. It occurred to me that I wasn't sure when the entire program was finished, so I deliberately misspelled it the last time. That way, I know for sure that the program exited properly.
Well, that ends the programming talk for a while. Next week, back to random nonsense!