2 # manincure.rb version 0.66
4 # This file is part of the HandBrake source code.
5 # Homepage: <http://handbrake.m0k.org/>.
6 # It may be used under the terms of the GNU General Public License.
8 # This script parses HandBrake's Mac presets into hashes, which can
9 # be displayed in various formats for use by the CLI and its wrappers.
11 # For handling command line arguments to the script
17 # CLI options: (code based on http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/index.html )
20 # --[no-]cli-raw, -r gives raw CLI for wiki
21 # --cli-parse, -p gives CLI strings for wrappers
22 # --api, -a gives preset code for test.c
23 # --api-list, -A gives CLI strings for --preset-list display
24 # --[no-]header, -h turns off banner display
25 options = OpenStruct.new
26 options.cliraw = false
27 options.cliparse = false
29 options.apilist = false
30 options.header = false
32 opts = OptionParser.new do |opts|
33 opts.banner = "Usage: manicure.rb [options]"
36 opts.separator "Options:"
38 opts.on("-r", "--cli-raw", "Gives example strings for the HB wiki") do |raw|
43 opts.on("-p", "--cli-parse", "Gives presets as wrapper-parseable CLI", " option strings") do |par|
44 options.cliparse = par
47 opts.on("-a", "--api", "Gives preset code for test.c") do |api|
51 opts.on("-A", "--api-list", "Gives code for test.c's --preset-list", " options") do |alist|
52 options.apilist = alist
55 opts.on("-H", "--Header", "Display a banner before each preset") do |head|
59 opts.on_tail("-h", "--help", "Show this message") do
69 # These arrays contain all the other presets and hashes that are going to be used.
70 # Yeah, they're global variables. In an object-oriented scripting language.
73 # This class parses the user's presets .plist into an array of hashes
76 attr_reader :hashMasterList
78 # Running initialization runs everything.
79 # Calling it will also call the parser
83 # Grab the user's home path
84 homeLocation = `echo $HOME`.chomp
86 # Use that to build a path to the presets .plist
87 inputFile = homeLocation+'/Library/Application Support/HandBrake/UserPresets.plist'
89 # Parse the presets into hashes
90 @hashMasterList = Plist::parse_xml( inputFile )
96 # This class displays the presets to stdout in various formats.
99 def initialize(hashMasterList, options)
101 @hashMasterList = hashMasterList
104 # A width of 40 gives nice, compact output.
108 displayCommandStrings
112 def displayCommandStrings # prints everything to screen
114 # Iterate through the hashes.
115 @hashMasterList.each do |hash|
117 # Check to see whether we've got a preset or afolder
119 # It's a top-level preset
120 displayIndividualPreset(hash, 0)
123 displayFolder( hash, 0 )
124 hash["ChildrenArray"].each do |subhash|
125 # Drill down to see its contents
126 if !subhash["Folder"]
128 displayIndividualPreset(subhash, 1)
131 displayFolder( subhash, 1 )
132 subhash["ChildrenArray"].each do |subsubhash|
133 # At this point we're far enough down we won't try to drill further
134 if !subsubhash["Folder"]
135 displayIndividualPreset(subsubhash, 2)
138 displayFolderCloser( 1 )
141 displayFolderCloser( 0 )
146 def displayIndividualPreset(hash, depth)
147 if @options.header == true
148 # First throw up a header to make each preset distinct
152 if @options.cliraw == true
153 # Show the preset's full CLI string equivalent
154 generateCLIString(hash, depth)
157 if @options.cliparse == true
158 generateCLIParse(hash, depth)
161 if @options.api == true
162 # Show the preset as code for test/test.c, HandBrakeCLI
163 generateAPIcalls(hash)
166 if @options.apilist == true
167 # Show the preset as print statements, for CLI wrappers to parse.
168 generateAPIList(hash, depth)
172 def displayHeader(hash) # A distinct banner to separate each preset
174 # Print a line of asterisks
175 puts "*" * @columnWidth
177 # Print the name, centered
178 puts '* '+hash["PresetName"].to_s.center(@columnWidth-4)+' *'
180 # Print a line of dashes
181 puts '~' * @columnWidth
183 # Print the description, centered and word-wrapped
184 puts hash["PresetDescription"].to_s.center(@columnWidth).gsub(/\n/," ").scan(/\S.{0,#{@columnWidth-2}}\S(?=\s|$)|\S+/)
186 # Print another line of dashes
187 puts '~' * @columnWidth
189 # Print the formats the preset uses
190 puts "#{hash["FileCodecs"]}".center(@columnWidth)
192 # Note if the preset isn't built-in
194 puts "Custom Preset".center(@columnWidth)
197 # Note if the preset is marked as default.
198 if hash["Default"] == 1
199 puts "This is your default preset.".center(@columnWidth)
202 # End with a line of tildes.
203 puts "~" * @columnWidth
207 def displayFolder( hash, depth )
209 if @options.cliraw == true
210 # Show the folder's full in a format that matches the CLI equivalents
211 generateCLIFolderString(hash, depth)
214 if @options.cliparse == true
215 # Show the folder in a format that matches the CLI wrapper equivalents
216 generateCLIFolderParse(hash, depth)
219 if @options.apilist == true
220 # Show the folder as print statements, for CLI wrappers to parse.
221 generateAPIFolderList(hash, depth)
226 def displayFolderCloser( depth )
227 if @options.cliraw == true
228 # Show the folder's full in a format that matches the CLI equivalents
229 generateCLIFolderCloserString( depth )
232 if @options.cliparse == true
233 # Show the folder in a format that matches the CLI wrapper equivalents
234 generateCLIFolderCloserParse( depth )
237 if @options.apilist == true
238 # Show the folder as print statements, for CLI wrappers to parse.
239 generateAPIFolderCloserList( depth )
243 def generateCLIFolderString( hash, depth ) # Shows the folder for the CLI equivalents
251 commandString << " " << hash["PresetName"] << "\n\n"
255 def generateCLIFolderCloserString( depth )
263 commandString << "\n\n"
267 def generateCLIString(hash, depth) # Makes a full CLI equivalent of a preset
272 commandString << './HandBrakeCLI -i DVD -o ~/Movies/movie.'
275 case hash["FileFormat"]
277 commandString << "mp4 "
279 commandString << "mkv "
283 if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
284 commandString << " -e "
285 case hash["VideoEncoder"]
287 commandString << "x264"
289 commandString << "theora"
294 case hash["VideoQualityType"]
296 commandString << " -S " << hash["VideoTargetSize"]
298 commandString << " -b " << hash["VideoAvgBitrate"]
300 commandString << " -q " << hash["VideoQualitySlider"].to_s
304 if hash["VideoFramerate"] != "Same as source"
305 if hash["VideoFramerate"] == "23.976 (NTSC Film)"
306 commandString << " -r " << "23.976"
307 elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
308 commandString << " -r " << "29.97"
309 elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
310 commandString << " -r " << "25"
312 commandString << " -r " << hash["VideoFramerate"]
315 if hash["VideoFrameratePFR"] == 1
316 commandString << " --pfr "
324 audioSamplerates = ""
327 audioCount = hash["AudioList"].size
329 hash["AudioList"].each do |audioTrack|
330 audioCount = audioCount - 1
333 audioBitrates << audioTrack["AudioBitrate"]
336 case audioTrack["AudioEncoder"]
338 audioEncoders << "ac3"
340 audioEncoders << "faac"
342 audioEncoders << "vorbis"
344 audioEncoders << "lame"
348 case audioTrack["AudioMixdown"]
350 audioMixdowns << "mono"
352 audioMixdowns << "stereo"
353 when /Dolby Surround/
354 audioMixdowns << "dpl1"
355 when /Dolby Pro Logic II/
356 audioMixdowns << "dpl2"
358 audioMixdowns << "6ch"
360 audioMixdowns << "auto"
364 audioSamplerates << audioTrack["AudioSamplerate"]
367 audioTracks << audioTrack["AudioTrack"].to_s
370 audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
376 audioSamplerates << ","
378 audioTrackDRCs << ","
382 commandString << " -a " << audioTracks
383 commandString << " -E " << audioEncoders
384 commandString << " -B " << audioBitrates
385 commandString << " -6 " << audioMixdowns
386 commandString << " -R " << audioSamplerates
387 commandString << " -D " << audioTrackDRCs
390 commandString << " -f "
391 case hash["FileFormat"]
393 commandString << "mp4"
395 commandString << "mkv"
399 if hash["Mp4iPodCompatible"].to_i == 1
400 commandString << " -I"
404 if hash["Mp4LargeFile"] == 1
405 commandString << " -4"
409 if hash["PictureAutoCrop"] == 0
410 commandString << " --crop "
411 commandString << hash["PictureTopCrop"].to_s
413 commandString << hash["PictureBottomCrop"].to_s
415 commandString << hash["PictureLeftCrop"].to_s
417 commandString << hash["PictureRightCrop"].to_s
421 if hash["PictureWidth"] != 0
422 commandString << " -X "
423 commandString << hash["PictureWidth"].to_s
425 if hash["PictureHeight"] != 0
426 commandString << " -Y "
427 commandString << hash["PictureHeight"].to_s
431 if hash["Subtitles"] && hash["Subtitles"] != "None"
432 if hash["Subtitles"] == "Autoselect"
433 commandString << " --subtitle-scan"
435 commandString << " -s "
436 commandString << hash["Subtitles"]
441 if hash["UsesPictureFilters"] == 1
443 case hash["PictureDeinterlace"]
445 commandString << " --deinterlace=\"fast\""
447 commandString << " --deinterlace=\slow\""
449 commandString << " --deinterlace=\"slower\""
451 commandString << " --deinterlace=\"slowest\""
454 case hash["PictureDenoise"]
456 commandString << " --denoise=\"weak\""
458 commandString << " --denoise=\"medium\""
460 commandString << " --denoise=\"strong\""
463 if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
464 if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
465 if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
470 if hash["PicturePAR"] == 1
471 commandString << " --strict-anamorphic"
472 elsif hash["PicturePAR"] == 2
473 commandString << " --loose-anamorphic"
474 elsif hash["PicturePAR"] == 3
475 commandString << " --custom-anamorphic"
479 if hash["ChapterMarkers"] == 1 then commandString << " -m" end
480 if hash["VideoGrayScale"] == 1 then commandString << " -g" end
481 if hash["VideoTwoPass"] == 1 then commandString << " -2" end
482 if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
485 if hash["x264Option"] != ""
486 commandString << " -x "
487 commandString << hash["x264Option"]
490 # That's it, print to screen now
493 #puts "*" * @columnWidth
498 def generateCLIFolderParse( hash, depth ) # Shows the folder for wrappers to parse
506 commandString << " " << hash["PresetName"] << "\n\n"
510 def generateCLIFolderCloserParse( depth )
518 commandString << "\n\n"
522 def generateCLIParse(hash, depth) # Makes a CLI equivalent of all user presets, for wrappers to parse
527 commandString << '+ ' << hash["PresetName"] << ":"
530 if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
531 commandString << " -e "
532 case hash["VideoEncoder"]
534 commandString << "x264"
536 commandString << "theora"
541 case hash["VideoQualityType"]
543 commandString << " -S " << hash["VideoTargetSize"]
545 commandString << " -b " << hash["VideoAvgBitrate"]
547 commandString << " -q " << hash["VideoQualitySlider"].to_s
551 if hash["VideoFramerate"] != "Same as source"
552 if hash["VideoFramerate"] == "23.976 (NTSC Film)"
553 commandString << " -r " << "23.976"
554 elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
555 commandString << " -r " << "29.97"
556 elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
557 commandString << " -r " << "25"
559 commandString << " -r " << hash["VideoFramerate"]
562 if hash["VideoFrameratePFR"] == 1
563 commandString << " --pfr "
571 audioSamplerates = ""
574 audioCount = hash["AudioList"].size
576 hash["AudioList"].each do |audioTrack|
577 audioCount = audioCount - 1
580 audioBitrates << audioTrack["AudioBitrate"]
583 case audioTrack["AudioEncoder"]
585 audioEncoders << "ac3"
587 audioEncoders << "faac"
589 audioEncoders << "vorbis"
591 audioEncoders << "lame"
595 case audioTrack["AudioMixdown"]
597 audioMixdowns << "mono"
599 audioMixdowns << "stereo"
600 when /Dolby Surround/
601 audioMixdowns << "dpl1"
602 when /Dolby Pro Logic II/
603 audioMixdowns << "dpl2"
605 audioMixdowns << "6ch"
607 audioMixdowns << "auto"
611 audioSamplerates << audioTrack["AudioSamplerate"]
614 audioTracks << audioTrack["AudioTrack"].to_s
617 audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
623 audioSamplerates << ","
625 audioTrackDRCs << ","
629 commandString << " -a " << audioTracks
630 commandString << " -E " << audioEncoders
631 commandString << " -B " << audioBitrates
632 commandString << " -6 " << audioMixdowns
633 commandString << " -R " << audioSamplerates
634 commandString << " -D " << audioTrackDRCs
637 commandString << " -f "
638 case hash["FileFormat"]
640 commandString << "mp4"
642 commandString << "mkv"
646 if hash["Mp4iPodCompatible"].to_i == 1
647 commandString << " -I"
651 if hash["Mp4LargeFile"] == 1
652 commandString << " -4"
656 if hash["PictureAutoCrop"] == 0
657 commandString << " --crop "
658 commandString << hash["PictureTopCrop"].to_s
660 commandString << hash["PictureBottomCrop"].to_s
662 commandString << hash["PictureLeftCrop"].to_s
664 commandString << hash["PictureRightCrop"].to_s
668 if hash["PictureWidth"] != 0
669 commandString << " -X "
670 commandString << hash["PictureWidth"].to_s
672 if hash["PictureHeight"] != 0
673 commandString << " -Y "
674 commandString << hash["PictureHeight"].to_s
678 if hash["Subtitles"] && hash["Subtitles"] != "None"
679 if hash["Subtitles"] == "Autoselect"
680 commandString << " --subtitle-scan"
682 commandString << " -s "
683 commandString << hash["Subtitles"]
688 if hash["UsesPictureFilters"] == 1
690 case hash["PictureDeinterlace"]
692 commandString << " --deinterlace=\"fast\""
694 commandString << " --deinterlace=\slow\""
696 commandString << " --deinterlace=\"slower\""
698 commandString << " --deinterlace=\"slowest\""
701 case hash["PictureDenoise"]
703 commandString << " --denoise=\"weak\""
705 commandString << " --denoise=\"medium\""
707 commandString << " --denoise=\"strong\""
710 if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
711 if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
712 if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
716 if hash["PicturePAR"] == 1
717 commandString << " --strict-anamorphic"
718 elsif hash["PicturePAR"] == 2
719 commandString << " --loose-anamorphic"
720 elsif hash["PicturePAR"] == 3
721 commandString << " --custom-anamorphic"
725 if hash["ChapterMarkers"] == 1 then commandString << " -m" end
726 if hash["VideoGrayScale"] == 1 then commandString << " -g" end
727 if hash["VideoTwoPass"] == 1 then commandString << " -2" end
728 if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
731 if hash["x264Option"] != ""
732 commandString << " -x "
733 commandString << hash["x264Option"]
736 # That's it, print to screen now
739 #puts "*" * @columnWidth
744 def generateAPIcalls(hash) # Makes a C version of the preset ready for coding into the CLI
746 commandString = "if (!strcmp(preset_name, \"" << hash["PresetName"] << "\"))\n{\n "
749 commandString << "if( !mux )\n "
750 commandString << "{\n "
752 case hash["FileFormat"]
754 commandString << " mux = " << "HB_MUX_MP4;\n "
756 commandString << " mux = " << "HB_MUX_MKV;\n "
758 commandString << "}\n "
761 if hash["Mp4iPodCompatible"].to_i == 1
762 commandString << "job->ipod_atom = 1;\n "
766 if hash["Mp4LargeFile"] == 1
767 commandString << "job->largeFileSize = 1;\n "
771 if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
772 commandString << "vcodec = "
773 case hash["VideoEncoder"]
775 commandString << "HB_VCODEC_X264;\n "
777 commandString << "HB_VCODEC_THEORA;\n "
782 case hash["VideoQualityType"]
784 commandString << "size = " << hash["VideoTargetSize"] << ";\n "
786 commandString << "job->vbitrate = " << hash["VideoAvgBitrate"] << ";\n "
788 commandString << "job->vquality = " << hash["VideoQualitySlider"].to_s << ";\n "
792 if hash["VideoFramerate"] != "Same as source"
793 if hash["VideoFramerate"] == "23.976 (NTSC Film)"
794 commandString << "job->vrate_base = " << "1126125;\n "
795 elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
796 commandString << "job->vrate_base = " << "900900;\n "
797 elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
798 commandString << "job->vrate_base = " << "1080000\n "
799 # Gotta add the rest of the framerates for completion's sake.
802 if hash["VideoFrameratePFR"] == 1
803 commandString << "job->cfr = 2;\n "
805 commandString << "job->cfr = 1;\n "
813 audioSamplerates = ""
816 audioCount = hash["AudioList"].size
818 hash["AudioList"].each do |audioTrack|
819 audioCount = audioCount - 1
822 audioBitrates << audioTrack["AudioBitrate"]
825 case audioTrack["AudioEncoder"]
827 audioEncoders << "ac3"
829 audioEncoders << "faac"
831 audioEncoders << "vorbis"
833 audioEncoders << "lame"
837 case audioTrack["AudioMixdown"]
839 audioMixdowns << "mono"
841 audioMixdowns << "stereo"
842 when /Dolby Surround/
843 audioMixdowns << "dpl1"
844 when /Dolby Pro Logic II/
845 audioMixdowns << "dpl2"
847 audioMixdowns << "6ch"
849 audioMixdowns << "auto"
853 audioSamplerates << audioTrack["AudioSamplerate"]
856 audioTracks << audioTrack["AudioTrack"].to_s
859 audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
865 audioSamplerates << ","
867 audioTrackDRCs << ","
871 commandString << "if( !atracks )\n "
872 commandString << "{\n "
873 commandString << " atracks = strdup(\"" << audioTracks
874 commandString << "\");\n "
875 commandString << "}\n "
877 commandString << "if( !acodecs )\n "
878 commandString << "{\n "
879 commandString << " acodecs = strdup(\"" << audioEncoders
880 commandString << "\");\n "
881 commandString << "}\n "
883 commandString << "if( !abitrates )\n "
884 commandString << "{\n "
885 commandString << " abitrates = strdup(\"" << audioBitrates
886 commandString << "\");\n "
887 commandString << "}\n "
889 commandString << "if( !mixdowns )\n "
890 commandString << "{\n "
891 commandString << " mixdowns = strdup(\"" << audioMixdowns
892 commandString << "\");\n "
893 commandString << "}\n "
895 commandString << "if( !arates )\n "
896 commandString << "{\n "
897 commandString << " arates = strdup(\"" << audioSamplerates
898 commandString << "\");\n "
899 commandString << "}\n "
901 commandString << "if( !dynamic_range_compression )\n "
902 commandString << "{\n "
903 commandString << " dynamic_range_compression = strdup(\"" << audioTrackDRCs
904 commandString << "\");\n "
905 commandString << "}\n "
908 if hash["PictureAutoCrop"] == 0
909 commandString << "job->crop[0] = " << hash["PictureTopCrop"].to_s << ";\n "
910 commandString << "job->crop[1] = " << hash["PictureBottomCrop"].to_s << ";\n "
911 commandString << "job->crop[2] = " << hash["PictureLeftCrop"].to_s << ";\n "
912 commandString << "job->crop[4] = " << hash["PictureRightCrop"].to_s << ";\n "
916 if hash["PictureWidth"] != 0
917 commandString << "maxWidth = "
918 commandString << hash["PictureWidth"].to_s << ";\n "
920 if hash["PictureHeight"] != 0
921 commandString << "maxHeight = "
922 commandString << hash["PictureHeight"].to_s << ";\n "
926 if hash["Subtitles"] != "None"
927 if hash["Subtitles"] == "Autoselect"
928 commandString << "subtitle_scan = 1;\n "
930 commandString << "job->subtitle = "
931 commandString << ( hash["Subtitles"].to_i - 1).to_s << ";\n "
936 if hash["x264Option"] != ""
937 commandString << "if( !x264opts )\n "
938 commandString << "{\n "
939 commandString << " x264opts = strdup(\""
940 commandString << hash["x264Option"] << "\");\n "
941 commandString << "}\n "
945 if hash["UsesPictureFilters"] == 1
947 case hash["PictureDeinterlace"]
949 commandString << "deinterlace = 1;\n "
950 commandString << "deinterlace_opt = \"-1\";\n "
952 commandString << "deinterlace = 1;\n "
953 commandString << "deinterlace_opt = \"2\";\n "
955 commandString << "deinterlace = 1;\n "
956 commandString << "deinterlace_opt = \"0\";\n "
958 commandString << "deinterlace = 1;\n "
959 commandString << "deinterlace_opt = \"1:-1:1\";\n "
962 case hash["PictureDenoise"]
964 commandString << "denoise = 1;\n "
965 commandString << "denoise_opt = \"2:1:2:3\";\n "
967 commandString << "denoise = 1;\n "
968 commandString << "denoise_opt = \"3:2:2:3\";\n "
970 commandString << "denoise = 1;\n "
971 commandString << "denoise_opt = \"7:7:5:5\";\n "
974 if hash["PictureDetelecine"] == 2 then commandString << "detelecine = 1;\n " end
975 if hash["PictureDeblock"] != 0
977 commandString << "deblock = 1;\n "
978 commandString << "deblock_opt = \"" << hash["PictureDeblock"].to_s << "\";\n "
980 if hash["PictureDecomb"] == 2 then commandString << "decomb = 1;\n " end
985 if hash["PicturePAR"] != 0
986 commandString << "if( !anamorphic_mode )\n "
987 commandString << "{\n "
988 if hash["PicturePAR"] == 1
989 commandString << " anamorphic_mode = 1;\n "
990 elsif hash["PicturePAR"] == 2
991 commandString << " anamorphic_mode = 2;\n "
992 elsif hash["PicturePAR"] == 3
993 commandString << " anamorphic_mode = 3;\n "
995 commandString << "}\n "
999 if hash["ChapterMarkers"] == 1 then commandString << "job->chapter_markers = 1;\n " end
1000 if hash["VideoGrayScale"] == 1 then commandString << "job->grayscale = 1;\n " end
1001 if hash["VideoTwoPass"] == 1 then commandString << "twoPass = 1;\n " end
1002 if hash["VideoTurboTwoPass"] == 1 then commandString << "turbo_opts_enabled = 1;\n" end
1003 commandString << "\n"
1004 commandString << "}"
1006 # That's it, print to screen now
1008 #puts "*" * @columnWidth
1012 def generateAPIFolderList( hash, depth )
1015 commandString << " printf(\"\\n"
1017 commandString << " "
1020 commandString << "<"
1022 commandString << " " << hash["PresetName"]
1023 commandString << "\\n\");\n\n"
1027 def generateAPIFolderCloserList( depth )
1030 commandString << " printf(\"\\n"
1032 commandString << " "
1035 commandString << ">"
1037 commandString << "\\n\");\n\n"
1041 def generateAPIList(hash, depth) # Makes a list of the CLI options a built-in CLI preset uses, for wrappers to parse
1043 commandString << " printf(\"\\n"
1045 commandString << " "
1048 commandString << "+ " << hash["PresetName"] << ": "
1051 if hash["VideoEncoder"] != "MPEG-4 (FFmpeg)"
1052 commandString << " -e "
1053 case hash["VideoEncoder"]
1055 commandString << "x264 "
1057 commandString << "theora "
1062 case hash["VideoQualityType"]
1064 commandString << " -S " << hash["VideoTargetSize"]
1066 commandString << " -b " << hash["VideoAvgBitrate"]
1068 commandString << " -q " << hash["VideoQualitySlider"].to_s
1072 if hash["VideoFramerate"] != "Same as source"
1073 if hash["VideoFramerate"] == "23.976 (NTSC Film)"
1074 commandString << " -r " << "23.976"
1075 elsif hash["VideoFramerate"] == "29.97 (NTSC Video)"
1076 commandString << " -r " << "29.97"
1077 elsif hash["VideoFramerate"] == "25 (PAL Film/Video)"
1078 commandString << " -r " << "25"
1080 commandString << " -r " << hash["VideoFramerate"]
1083 if hash["VideoFrameratePFR"] == 1
1084 commandString << " --pfr "
1092 audioSamplerates = ""
1095 audioCount = hash["AudioList"].size
1097 hash["AudioList"].each do |audioTrack|
1098 audioCount = audioCount - 1
1101 audioBitrates << audioTrack["AudioBitrate"]
1104 case audioTrack["AudioEncoder"]
1106 audioEncoders << "ac3"
1108 audioEncoders << "faac"
1110 audioEncoders << "vorbis"
1112 audioEncoders << "lame"
1116 case audioTrack["AudioMixdown"]
1118 audioMixdowns << "mono"
1120 audioMixdowns << "stereo"
1121 when /Dolby Surround/
1122 audioMixdowns << "dpl1"
1123 when /Dolby Pro Logic II/
1124 audioMixdowns << "dpl2"
1126 audioMixdowns << "6ch"
1128 audioMixdowns << "auto"
1132 audioSamplerates << audioTrack["AudioSamplerate"]
1135 audioTracks << audioTrack["AudioTrack"].to_s
1138 audioTrackDRCs << audioTrack["AudioTrackDRCSlider"].to_s
1141 audioBitrates << ","
1142 audioEncoders << ","
1143 audioMixdowns << ","
1144 audioSamplerates << ","
1146 audioTrackDRCs << ","
1150 commandString << " -a " << audioTracks
1151 commandString << " -E " << audioEncoders
1152 commandString << " -B " << audioBitrates
1153 commandString << " -6 " << audioMixdowns
1154 commandString << " -R " << audioSamplerates
1155 commandString << " -D " << audioTrackDRCs
1158 commandString << " -f "
1159 case hash["FileFormat"]
1161 commandString << "mp4"
1163 commandString << "mkv"
1167 if hash["Mp4iPodCompatible"].to_i == 1
1168 commandString << " -I"
1172 if hash["Mp4LargeFile"] == 1
1173 commandString << " -4"
1177 if hash["PictureAutoCrop"] == 0
1178 commandString << " --crop "
1179 commandString << hash["PictureTopCrop"].to_s
1180 commandString << ":"
1181 commandString << hash["PictureBottomCrop"].to_s
1182 commandString << ":"
1183 commandString << hash["PictureLeftCrop"].to_s
1184 commandString << ":"
1185 commandString << hash["PictureRightCrop"].to_s
1189 if hash["PictureWidth"] != 0
1190 commandString << " -X "
1191 commandString << hash["PictureWidth"].to_s
1193 if hash["PictureHeight"] != 0
1194 commandString << " -Y "
1195 commandString << hash["PictureHeight"].to_s
1199 if hash["Subtitles"] && hash["Subtitles"] != "None"
1200 if hash["Subtitles"] == "Autoselect"
1201 commandString << " --subtitle-scan"
1203 commandString << " -s "
1204 commandString << hash["Subtitles"]
1209 if hash["UsesPictureFilters"] == 1
1211 case hash["PictureDeinterlace"]
1213 commandString << " --deinterlace=\\\"fast\\\""
1215 commandString << " --deinterlace=\\\slow\\\""
1217 commandString << " --deinterlace=\\\"slower\\\""
1219 commandString << " --deinterlace=\\\"slowest\\\""
1222 case hash["PictureDenoise"]
1224 commandString << " --denoise=\\\"weak\\\""
1226 commandString << " --denoise=\\\"medium\\\""
1228 commandString << " --denoise=\\\"strong\\\""
1231 if hash["PictureDetelecine"] == 2 then commandString << " --detelecine" end
1232 if hash["PictureDeblock"] != 0 then commandString << " --deblock=" << hash["PictureDeblock"].to_s end
1233 if hash["PictureDecomb"] == 2 then commandString << " --decomb" end
1237 if hash["PicturePAR"] == 1
1238 commandString << " --strict-anamorphic"
1239 elsif hash["PicturePAR"] == 2
1240 commandString << " --loose-anamorphic"
1241 elsif hash["PicturePAR"] == 3
1242 commandString << " --custom-anamorphic"
1246 if hash["ChapterMarkers"] == 1 then commandString << " -m" end
1247 if hash["VideoGrayScale"] == 1 then commandString << " -g" end
1248 if hash["VideoTwoPass"] == 1 then commandString << " -2" end
1249 if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end
1252 if hash["x264Option"] != ""
1253 commandString << " -x "
1254 commandString << hash["x264Option"]
1257 commandString << "\\n\");"
1259 # That's it, print to screen now
1266 # First grab the specified CLI options
1267 options = readOptions
1269 # Only run if one of the useful CLI flags have been passed
1270 if options.cliraw == true || options.cliparse == true || options.api == true || options.apilist == true
1271 # This line is the ignition -- generates hashes of
1272 # presets and then displays them to the screen
1273 # with the options the user selects on the CLI.
1274 Display.new( Presets.new.hashMasterList, options )
1276 # Direct the user to the help
1277 puts "\n\tUsage: manicure.rb [options]"
1278 puts "\tSee help with -h or --help"