diff --git a/autoProcessMedia.cfg.spec b/autoProcessMedia.cfg.spec index 43c1be19..5396f7d5 100644 --- a/autoProcessMedia.cfg.spec +++ b/autoProcessMedia.cfg.spec @@ -237,18 +237,52 @@ # Only works on Linux. Highest priority is -20, lowest priority is 19. niceness = 0 ignoreExtensions = .avi,.mkv,.mp4 - outputVideoExtension = .mp4 - outputVideoCodec = libx264 - outputVideoPreset = medium - outputVideoFramerate = 24 - outputVideoBitrate = 800k - outputAudioCodec = libmp3lame - outputAudioBitrate = 128k - outputSubtitleCodec = # outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. outputFastStart = 0 # outputQualityPercent. used as -q:a value. 0 will disable this from being used. outputQualityPercent = 0 + # outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. + outputVideoPath = + # processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files. + processOutput = 0 + # audioLanguage. set the 3 letter language code you want as your primary audio track. + audioLanguage = eng + # allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available. + allAudioLanguages = 0 + # subLanguages. create a list of languages in the order you want them in your subtitles. + # (future versions I hope to support sub downlaod) + subLanguages = eng,spa,fre + # allSubLanguages. 1 will keep all exisiting sub languages. 0 will discare those not in your list above. + allSubLanguages = 0 + # embedSubs. 1 will embded external sub/srt subs into your video if this is supported. + embedSubs = 1 + # burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs) + burnInSubtitle = 0 + # extractSubs. 1 will extract subs from the video file and save these as external srt files. + extractSubs = 0 + # externalSubDir. set the directory where subs should be saved (if not the same directory as the video) + externalSubDir = + # outputDefault. Loads default configs for the selected device. The remaining options below are ignored. + # If you want to use your own profile, leave this blank and set the remaining options below. + # outputDefault profiles allowed: iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, Roku-1080p, Roku-720p, Roku-480p + outputDefault = + #### Define custom settings below. + outputVideoExtension = .mp4 + outputVideoCodec = libx264 + VideoCodecAllow = + outputVideoPreset = medium + outputVideoFramerate = 24 + outputVideoBitrate = 800000 + outputAudioCodec = ac3 + AudioCodecAllow = + outputAudioBitrate = 160000 + outputAudioTrack2Codec = libfaac + AudioCodec2Allow = + outputAudioTrack2Bitrate = 128000 + outputAudioOtherCodec = libmp3lame + AudioOtherCodecAllow = + outputAudioOtherBitrate = 128000 + outputSubtitleCodec = [WakeOnLan] ###### set wake = 1 to send WOL broadcast to the mac and test the server (e.g. xbmc) the host and port specified. diff --git a/nzbToCouchPotato.py b/nzbToCouchPotato.py index c37d82ee..9c1da5a1 100755 --- a/nzbToCouchPotato.py +++ b/nzbToCouchPotato.py @@ -107,20 +107,96 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# ignore extensions +# set niceness level. +# +# Only works on Linux. Highest priority is -20, lowest priority is 19. +#niceness = 0 + +# ignore extensions. # # list of extensions that won't be transcoded. #ignoreExtensions=.avi,.mkv +# outputFastStart (0,1). +# +# outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. +#outputFastStart = 0 + +# outputVideoPath. +# +# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. +#outputVideoPath = + +# processOutput (0,1). +# +# processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files. +#processOutput = 0 + +# audioLanguage. +# +# audioLanguage. set the 3 letter language code you want as your primary audio track. +#audioLanguage = eng + +# allAudioLanguages (0,1). +# +# allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available. +#allAudioLanguages = 0 + +# subLanguages. +# +# subLanguages. create a list of languages in the order you want them in your subtitles. +# (future versions I hope to support sub downlaod) +#subLanguages = eng,spa,fre + +# allSubLanguages (0,1). +# +# allSubLanguages. 1 will keep all exisiting sub languages. 0 will discare those not in your list above. +#allSubLanguages = 0 + +# embedSubs (0,1). +# +# embedSubs. 1 will embded external sub/srt subs into your video if this is supported. +#embedSubs = 1 + +# burnInSubtitle (0,1). +# +# burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs) +#burnInSubtitle = 0 + +# extractSubs (0,1). +# +# extractSubs. 1 will extract subs from the video file and save these as external srt files. +#extractSubs = 0 + +# externalSubDir. +# +# externalSubDir. set the directory where subs should be saved (if not the same directory as the video) +#externalSubDir = + +# outputDefault (None, iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, Roku-1080p, Roku-720p, Roku-480p). +# +# outputDefault. Loads default configs for the selected device. The remaining options below are ignored. +# If you want to use your own profile, set None and set the remaining options below. +#outputDefault = None + # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 +#VideoCodecAllow = #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame +#AudioCodecAllow = #outputAudioBitrate=128k -#outputSubtitleCodec= +#outputQualityPercent = 0 +#outputAudioTrack2Codec = libfaac +#AudioCodec2Allow = +#outputAudioTrack2Bitrate = 128k +#outputAudioOtherCodec = libmp3lame +#AudioOtherCodecAllow = +#outputAudioOtherBitrate = 128k +#outputSubtitleCodec = ## WakeOnLan diff --git a/nzbToMedia.py b/nzbToMedia.py index 8000edd2..ed5869e3 100755 --- a/nzbToMedia.py +++ b/nzbToMedia.py @@ -303,20 +303,96 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# ignore extensions +# set niceness level. +# +# Only works on Linux. Highest priority is -20, lowest priority is 19. +#niceness = 0 + +# ignore extensions. # # list of extensions that won't be transcoded. #ignoreExtensions=.avi,.mkv +# outputFastStart (0,1). +# +# outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. +#outputFastStart = 0 + +# outputVideoPath. +# +# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. +#outputVideoPath = + +# processOutput (0,1). +# +# processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files. +#processOutput = 0 + +# audioLanguage. +# +# audioLanguage. set the 3 letter language code you want as your primary audio track. +#audioLanguage = eng + +# allAudioLanguages (0,1). +# +# allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available. +#allAudioLanguages = 0 + +# subLanguages. +# +# subLanguages. create a list of languages in the order you want them in your subtitles. +# (future versions I hope to support sub downlaod) +#subLanguages = eng,spa,fre + +# allSubLanguages (0,1). +# +# allSubLanguages. 1 will keep all exisiting sub languages. 0 will discare those not in your list above. +#allSubLanguages = 0 + +# embedSubs (0,1). +# +# embedSubs. 1 will embded external sub/srt subs into your video if this is supported. +#embedSubs = 1 + +# burnInSubtitle (0,1). +# +# burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs) +#burnInSubtitle = 0 + +# extractSubs (0,1). +# +# extractSubs. 1 will extract subs from the video file and save these as external srt files. +#extractSubs = 0 + +# externalSubDir. +# +# externalSubDir. set the directory where subs should be saved (if not the same directory as the video) +#externalSubDir = + +# outputDefault (None, iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, Roku-1080p, Roku-720p, Roku-480p). +# +# outputDefault. Loads default configs for the selected device. The remaining options below are ignored. +# If you want to use your own profile, set None and set the remaining options below. +#outputDefault = None + # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 +#VideoCodecAllow = #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame +#AudioCodecAllow = #outputAudioBitrate=128k -#outputSubtitleCodec= +#outputQualityPercent = 0 +#outputAudioTrack2Codec = libfaac +#AudioCodec2Allow = +#outputAudioTrack2Bitrate = 128k +#outputAudioOtherCodec = libmp3lame +#AudioOtherCodecAllow = +#outputAudioOtherBitrate = 128k +#outputSubtitleCodec = ## WakeOnLan diff --git a/nzbToNzbDrone.py b/nzbToNzbDrone.py index 709435d0..8a1db46f 100755 --- a/nzbToNzbDrone.py +++ b/nzbToNzbDrone.py @@ -97,20 +97,96 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# ignore extensions +# set niceness level. +# +# Only works on Linux. Highest priority is -20, lowest priority is 19. +#niceness = 0 + +# ignore extensions. # # list of extensions that won't be transcoded. #ignoreExtensions=.avi,.mkv +# outputFastStart (0,1). +# +# outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. +#outputFastStart = 0 + +# outputVideoPath. +# +# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. +#outputVideoPath = + +# processOutput (0,1). +# +# processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files. +#processOutput = 0 + +# audioLanguage. +# +# audioLanguage. set the 3 letter language code you want as your primary audio track. +#audioLanguage = eng + +# allAudioLanguages (0,1). +# +# allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available. +#allAudioLanguages = 0 + +# subLanguages. +# +# subLanguages. create a list of languages in the order you want them in your subtitles. +# (future versions I hope to support sub downlaod) +#subLanguages = eng,spa,fre + +# allSubLanguages (0,1). +# +# allSubLanguages. 1 will keep all exisiting sub languages. 0 will discare those not in your list above. +#allSubLanguages = 0 + +# embedSubs (0,1). +# +# embedSubs. 1 will embded external sub/srt subs into your video if this is supported. +#embedSubs = 1 + +# burnInSubtitle (0,1). +# +# burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs) +#burnInSubtitle = 0 + +# extractSubs (0,1). +# +# extractSubs. 1 will extract subs from the video file and save these as external srt files. +#extractSubs = 0 + +# externalSubDir. +# +# externalSubDir. set the directory where subs should be saved (if not the same directory as the video) +#externalSubDir = + +# outputDefault (None, iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, Roku-1080p, Roku-720p, Roku-480p). +# +# outputDefault. Loads default configs for the selected device. The remaining options below are ignored. +# If you want to use your own profile, set None and set the remaining options below. +#outputDefault = None + # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 +#VideoCodecAllow = #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame +#AudioCodecAllow = #outputAudioBitrate=128k -#outputSubtitleCodec= +#outputQualityPercent = 0 +#outputAudioTrack2Codec = libfaac +#AudioCodec2Allow = +#outputAudioTrack2Bitrate = 128k +#outputAudioOtherCodec = libmp3lame +#AudioOtherCodecAllow = +#outputAudioOtherBitrate = 128k +#outputSubtitleCodec = ## WakeOnLan diff --git a/nzbToSickBeard.py b/nzbToSickBeard.py index afee486b..2ff207e1 100755 --- a/nzbToSickBeard.py +++ b/nzbToSickBeard.py @@ -115,20 +115,96 @@ # set to 1 to cretae a new file or 0 to replace the original #duplicate=1 -# ignore extensions +# set niceness level. +# +# Only works on Linux. Highest priority is -20, lowest priority is 19. +#niceness = 0 + +# ignore extensions. # # list of extensions that won't be transcoded. #ignoreExtensions=.avi,.mkv +# outputFastStart (0,1). +# +# outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used. +#outputFastStart = 0 + +# outputVideoPath. +# +# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable. +#outputVideoPath = + +# processOutput (0,1). +# +# processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files. +#processOutput = 0 + +# audioLanguage. +# +# audioLanguage. set the 3 letter language code you want as your primary audio track. +#audioLanguage = eng + +# allAudioLanguages (0,1). +# +# allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available. +#allAudioLanguages = 0 + +# subLanguages. +# +# subLanguages. create a list of languages in the order you want them in your subtitles. +# (future versions I hope to support sub downlaod) +#subLanguages = eng,spa,fre + +# allSubLanguages (0,1). +# +# allSubLanguages. 1 will keep all exisiting sub languages. 0 will discare those not in your list above. +#allSubLanguages = 0 + +# embedSubs (0,1). +# +# embedSubs. 1 will embded external sub/srt subs into your video if this is supported. +#embedSubs = 1 + +# burnInSubtitle (0,1). +# +# burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs) +#burnInSubtitle = 0 + +# extractSubs (0,1). +# +# extractSubs. 1 will extract subs from the video file and save these as external srt files. +#extractSubs = 0 + +# externalSubDir. +# +# externalSubDir. set the directory where subs should be saved (if not the same directory as the video) +#externalSubDir = + +# outputDefault (None, iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, Roku-1080p, Roku-720p, Roku-480p). +# +# outputDefault. Loads default configs for the selected device. The remaining options below are ignored. +# If you want to use your own profile, set None and set the remaining options below. +#outputDefault = None + # ffmpeg output settings. #outputVideoExtension=.mp4 #outputVideoCodec=libx264 +#VideoCodecAllow = #outputVideoPreset=medium #outputVideoFramerate=24 #outputVideoBitrate=800k #outputAudioCodec=libmp3lame +#AudioCodecAllow = #outputAudioBitrate=128k -#outputSubtitleCodec= +#outputQualityPercent = 0 +#outputAudioTrack2Codec = libfaac +#AudioCodec2Allow = +#outputAudioTrack2Bitrate = 128k +#outputAudioOtherCodec = libmp3lame +#AudioOtherCodecAllow = +#outputAudioOtherBitrate = 128k +#outputSubtitleCodec = ## WakeOnLan diff --git a/nzbtomedia/__init__.py b/nzbtomedia/__init__.py index 168630aa..a13959a8 100644 --- a/nzbtomedia/__init__.py +++ b/nzbtomedia/__init__.py @@ -119,15 +119,36 @@ CATEGORIES = [] TRANSCODE = None FFMPEG_PATH = None DUPLICATE = None -IGNOREEXTENSIONS = None -OUTPUTVIDEOEXTENSION = None -OUTPUTVIDEOCODEC = None -OUTPUTVIDEOPRESET = None -OUTPUTVIDEOFRAMERATE = None -OUTPUTVIDEOBITRATE = None -OUTPUTAUDIOCODEC = None -OUTPUTAUDIOBITRATE = None -OUTPUTSUBTITLECODEC = None +IGNOREEXTENSIONS = [] +VEXTENSION = None +OUTPUTVIDEOPATH = None +PROCESSOUTPUT = False +ALANGUAGE = None +AINCLUDE = False +SLANGUAGES = [] +SINCLUDE = False +SUBSDIR = None +ALLOWSUBS = False +SEXTRACT = False +SEMBED = False +BURN = False +DEFAULTS = None +VCODEC = None +VCODEC_ALLOW = [] +VPRESET = None +VFRAMERATE = None +VBITRATE = None +VRESOLUTION = None +ACODEC = None +ACODEC_ALLOW = [] +ABITRATE = None +ACODEC2 = None +ACODEC2_ALLOW = [] +ABITRATE2 = None +ACODEC3 = None +ACODEC3_ALLOW = [] +ABITRATE3 = None +SCODEC = None OUTPUTFASTSTART = None OUTPUTQUALITYPERCENT = None FFMPEG = None @@ -152,13 +173,16 @@ def initialize(section=None): global NZBGET_POSTPROCESS_ERROR, NZBGET_POSTPROCESS_NONE, NZBGET_POSTPROCESS_PARCHECK, NZBGET_POSTPROCESS_SUCCESS, \ NZBTOMEDIA_TIMEOUT, FORKS, FORK_DEFAULT, FORK_FAILED_TORRENT, FORK_FAILED, SICKBEARD_TORRENT, SICKBEARD_FAILED, \ NZBTOMEDIA_BRANCH, NZBTOMEDIA_VERSION, NEWEST_VERSION, NEWEST_VERSION_STRING, VERSION_NOTIFY, SYS_ARGV, CFG, \ - SABNZB_NO_OF_ARGUMENTS, SABNZB_0717_NO_OF_ARGUMENTS, CATEGORIES, TORRENT_CLIENTAGENT, USELINK, OUTPUTDIRECTORY, NOFLATTEN, \ - UTORRENTPWD, UTORRENTUSR, UTORRENTWEBUI, DELUGEHOST, DELUGEPORT, DELUGEUSR, DELUGEPWD, TRANSMISSIONHOST, TRANSMISSIONPORT, \ - TRANSMISSIONPWD, TRANSMISSIONUSR, COMPRESSEDCONTAINER, MEDIACONTAINER, METACONTAINER, SECTIONS, \ - __INITIALIZED__, AUTO_UPDATE, APP_FILENAME, USER_DELAY, APP_NAME, TRANSCODE, GIT_PATH, GIT_USER, \ + SABNZB_NO_OF_ARGUMENTS, SABNZB_0717_NO_OF_ARGUMENTS, CATEGORIES, TORRENT_CLIENTAGENT, USELINK, OUTPUTDIRECTORY, \ + NOFLATTEN, UTORRENTPWD, UTORRENTUSR, UTORRENTWEBUI, DELUGEHOST, DELUGEPORT, DELUGEUSR, DELUGEPWD, \ + TRANSMISSIONHOST, TRANSMISSIONPORT, TRANSMISSIONPWD, TRANSMISSIONUSR, COMPRESSEDCONTAINER, MEDIACONTAINER, \ + METACONTAINER, SECTIONS, \ + __INITIALIZED__, AUTO_UPDATE, APP_FILENAME, USER_DELAY, APP_NAME, TRANSCODE, DEFAULTS, GIT_PATH, GIT_USER, \ GIT_BRANCH, GIT_REPO, SYS_ENCODING, NZB_CLIENTAGENT, SABNZBDHOST, SABNZBDPORT, SABNZBDAPIKEY, \ - DUPLICATE, IGNOREEXTENSIONS, OUTPUTVIDEOEXTENSION, OUTPUTVIDEOCODEC, OUTPUTVIDEOPRESET, OUTPUTVIDEOFRAMERATE, LOG_DB, \ - OUTPUTVIDEOBITRATE, OUTPUTAUDIOCODEC, OUTPUTAUDIOBITRATE, OUTPUTSUBTITLECODEC, OUTPUTFASTSTART, OUTPUTQUALITYPERCENT, \ + DUPLICATE, IGNOREEXTENSIONS, VEXTENSION, OUTPUTVIDEOPATH, PROCESSOUTPUT, VCODEC, VCODEC_ALLOW, VPRESET, \ + VFRAMERATE, LOG_DB, VBITRATE, VRESOLUTION, ALANGUAGE, AINCLUDE, ACODEC, ACODEC_ALLOW, ABITRATE, \ + ACODEC2, ACODEC2_ALLOW, ABITRATE2, ACODEC3, ACODEC3_ALLOW, ABITRATE3, ALLOWSUBS, SEXTRACT, SEMBED, SLANGUAGES, \ + SINCLUDE, SUBSDIR, SCODEC, OUTPUTFASTSTART, OUTPUTQUALITYPERCENT, BURN, \ NICENESS, LOG_DEBUG, FORCE_CLEAN, FFMPEG_PATH, FFMPEG, FFPROBE, AUDIOCONTAINER, EXTCONTAINER, TORRENT_CLASS, \ DELETE_ORIGINAL, PASSWORDSFILE, USER_DELAY, USER_SCRIPT, USER_SCRIPT_CLEAN, USER_SCRIPT_MEDIAEXTENSIONS, \ USER_SCRIPT_PARAM, USER_SCRIPT_RUNONCE, USER_SCRIPT_SUCCESSCODES, DOWNLOADINFO, CHECK_MEDIA, SAFE_MODE, \ @@ -300,18 +324,169 @@ def initialize(section=None): TRANSCODE = int(CFG["Transcoder"]["transcode"]) DUPLICATE = int(CFG["Transcoder"]["duplicate"]) IGNOREEXTENSIONS = (CFG["Transcoder"]["ignoreExtensions"]) - OUTPUTVIDEOEXTENSION = CFG["Transcoder"]["outputVideoExtension"].strip() - OUTPUTVIDEOCODEC = CFG["Transcoder"]["outputVideoCodec"].strip() - OUTPUTVIDEOPRESET = CFG["Transcoder"]["outputVideoPreset"].strip() - OUTPUTVIDEOFRAMERATE = CFG["Transcoder"]["outputVideoFramerate"].strip() - OUTPUTVIDEOBITRATE = CFG["Transcoder"]["outputVideoBitrate"].strip() - OUTPUTAUDIOCODEC = CFG["Transcoder"]["outputAudioCodec"].strip() - OUTPUTAUDIOBITRATE = CFG["Transcoder"]["outputAudioBitrate"].strip() - OUTPUTSUBTITLECODEC = CFG["Transcoder"]["outputSubtitleCodec"].strip() + if isinstance(IGNOREEXTENSIONS, str): IGNOREEXTENSIONS = IGNOREEXTENSIONS.split(',') OUTPUTFASTSTART = int(CFG["Transcoder"]["outputFastStart"]) OUTPUTQUALITYPERCENT = int(CFG["Transcoder"]["outputQualityPercent"]) NICENESS = int(CFG["Transcoder"]["niceness"]) - if isinstance(IGNOREEXTENSIONS, str): IGNOREEXTENSIONS = IGNOREEXTENSIONS.split(',') + OUTPUTVIDEOPATH = CFG["Transcoder"]["outputVideoPath"] + PROCESSOUTPUT = int(CFG["Transcoder"]["processOutput"]) + ALANGUAGE = CFG["Transcoder"]["audioLanguage"] + AINCLUDE = int(CFG["Transcoder"]["allAudioLanguages"]) + SLANGUAGES = CFG["Transcoder"]["subLanguages"] + if isinstance(SLANGUAGES, str): SLANGUAGES = SLANGUAGES.split(',') + SINCLUDE = int(CFG["Transcoder"]["allSubLanguages"]) + SEXTRACT = int(CFG["Transcoder"]["extractSubs"]) + SEMBED = int(CFG["Transcoder"]["embedSubs"]) + SUBSDIR = CFG["Transcoder"]["externalSubDir"] + VEXTENSION = CFG["Transcoder"]["outputVideoExtension"].strip() + VCODEC = CFG["Transcoder"]["outputVideoCodec"].strip() + VCODEC_ALLOW = CFG["Transcoder"]["VideoCodecAllow"].strip() + if isinstance(VCODEC_ALLOW, str): VCODEC_ALLOW = VCODEC_ALLOW.split(',') + VPRESET = CFG["Transcoder"]["outputVideoPreset"].strip() + VFRAMERATE = float(CFG["Transcoder"]["outputVideoFramerate"].strip()) + VBITRATE = int((CFG["Transcoder"]["outputVideoBitrate"].strip()).replace('k','000')) + VRESOLUTION = CFG["Transcoder"]["outputVideoResolution"] + ACODEC = CFG["Transcoder"]["outputAudioCodec"].strip() + ACODEC_ALLOW = CFG["Transcoder"]["AudioCodecAllow"].strip() + if isinstance(ACODEC_ALLOW, str): ACODEC_ALLOW = ACODEC_ALLOW.split(',') + ABITRATE = int((CFG["Transcoder"]["outputAudioBitrate"].strip()).replace('k','000')) + ACODEC2 = CFG["Transcoder"]["outputAudioTrack2Codec"].strip() + ACODEC2_ALLOW = CFG["Transcoder"]["AudioCodec2Allow"].strip() + if isinstance(ACODEC2_ALLOW, str): ACODEC2_ALLOW = ACODEC2_ALLOW.split(',') + ABITRATE2 = int((CFG["Transcoder"]["outputAudioTrack2Bitrate"].strip()).replace('k','000')) + ACODEC3 = CFG["Transcoder"]["outputAudioOtherCodec"].strip() + ACODEC3_ALLOW = CFG["Transcoder"]["AudioOtherCodecAllow"].strip() + if isinstance(ACODEC3_ALLOW, str): ACODEC3_ALLOW = ACODEC3_ALLOW.split(',') + ABITRATE3 = int((CFG["Transcoder"]["outputAudioOtherBitrate"].strip()).replace('k','000')) + SCODEC = CFG["Transcoder"]["outputSubtitleCodec"].strip() + BURN = int(CFG["Transcoder"]["burnInSubtitle"].strip()) + DEFAULTS = CFG["Transcoder"]["outputDefault"].strip() + + allow_subs = ['.mkv','.mp4', '.m4v', 'asf', 'wma', 'wmv'] + codec_alias = { + 'libx264':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'libmp3lame':['libmp3lame', 'mp3'], + 'libfaac':['libfaac', 'aac', 'faac'] + } + transcode_defaults = { + 'iPad':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':None,'VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':None, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'iPad-1080p':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':'1920:1080','VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':None, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'iPad-720p':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':'1280:720','VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':None, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'Apple-TV':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':'1280:720','VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'ac3','ACODEC_ALLOW':['ac3'],'ABITRATE':None, + 'ACODEC2':'libfaac','ACODEC2_ALLOW':['libfaac'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'iPod':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':'1280:720','VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':128000, + 'ACODEC2':None,'ACODEC2_ALLOW':[],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'iPhone':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':'460:320','VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':128000, + 'ACODEC2':None,'ACODEC2_ALLOW':[],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'PS3':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':None,'VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'ac3','ACODEC_ALLOW':['ac3'],'ABITRATE':None, + 'ACODEC2':'libfaac','ACODEC2_ALLOW':['libfaac'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'Roku-480p':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':None,'VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':128000, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'Roku-720p':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':None,'VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':128000, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + }, + 'Roku-1080p':{ + 'VEXTENSION':'.mp4','VCODEC':'libx264','VPRESET':None,'VFRAMERATE':None,'VBITRATE':None, + 'VRESOLUTION':None,'VCODEC_ALLOW':['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'], + 'ACODEC':'libfaac','ACODEC_ALLOW':['libfaac'],'ABITRATE':160000, + 'ACODEC2':'ac3','ACODEC2_ALLOW':['ac3'],'ABITRATE2':None, + 'ACODEC3':None,'ACODEC3_ALLOW2':[],'ABITRATE3':None, + 'SCODEC':None + } + } + if DEFAULTS and DEFAULTS in transcode_defaults: + VEXTENSION = transcode_defaults[DEFAULTS]['VEXTENSION'] + VCODEC = transcode_defaults[DEFAULTS]['VCODEC'] + VPRESET = transcode_defaults[DEFAULTS]['VPRESET'] + VFRAMERATE = transcode_defaults[DEFAULTS]['VFRAMERATE'] + VBITRATE = transcode_defaults[DEFAULTS]['VBITRATE'] + VRESOLUTION = transcode_defaults[DEFAULTS]['VRESOLUTION'] + VCODEC_ALLOW = transcode_defaults[DEFAULTS]['VCODEC_ALLOW'] + ACODEC = transcode_defaults[DEFAULTS]['ACODEC'] + ACODEC_ALLOW = transcode_defaults[DEFAULTS]['ACODEC_ALLOW'] + ABITRATE = transcode_defaults[DEFAULTS]['ABITRATE'] + ACODEC2 = transcode_defaults[DEFAULTS]['ACODEC2'] + ACODEC2_ALLOW = transcode_defaults[DEFAULTS]['ACODEC2_ALLOW'] + ABITRATE2 = transcode_defaults[DEFAULTS]['ABITRATE2'] + ACODEC3 = transcode_defaults[DEFAULTS]['ACODEC3'] + ACODEC3_ALLOW = transcode_defaults[DEFAULTS]['ACODEC3_ALLOW'] + ABITRATE3 = transcode_defaults[DEFAULTS]['ABITRATE3'] + SCODEC = transcode_defaults[DEFAULTS]['SCODEC'] + + if VEXTENSION in allow_subs: + ALLOWSUBS = 1 + if not VCODEC_ALLOW and VCODEC: VCODEC_ALLOW.extend([VCODEC]) + for codec in VCODEC_ALLOW: + if codec in codec_alias: + VCODEC_ALLOW.extend(codec_alias[codec]) + if not ACODEC_ALLOW and ACODEC: ACODEC_ALLOW.extend([ACODEC]) + for codec in ACODEC_ALLOW: + if codec in codec_alias: + ACODEC_ALLOW.extend(codec_alias[codec]) + if not ACODEC2_ALLOW and ACODEC2: ACODEC2_ALLOW.extend([ACODEC2]) + for codec in ACODEC2_ALLOW: + if codec in codec_alias: + ACODEC2_ALLOW.extend(codec_alias[codec]) + if not ACODEC3_ALLOW and ACODEC3: ACODEC3_ALLOW.extend([ACODEC3]) + for codec in ACODEC3_ALLOW: + if codec in codec_alias: + ACODEC3_ALLOW.extend(codec_alias[codec]) PASSWORDSFILE = CFG["passwords"]["PassWordFile"] diff --git a/nzbtomedia/autoProcess/autoProcessMovie.py b/nzbtomedia/autoProcess/autoProcessMovie.py index 3d4f0ca9..7c5c58af 100644 --- a/nzbtomedia/autoProcess/autoProcessMovie.py +++ b/nzbtomedia/autoProcess/autoProcessMovie.py @@ -184,9 +184,10 @@ class autoProcessMovie: if status == 0: if nzbtomedia.TRANSCODE == 1: - result = transcoder.Transcode_directory(dirName) + result, newDirName = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("Transcoding succeeded for files in %s" % (dirName), section) + dirName = newDirName else: logger.warning("Transcoding failed for files in %s" % (dirName), section) diff --git a/nzbtomedia/autoProcess/autoProcessTV.py b/nzbtomedia/autoProcess/autoProcessTV.py index 4e002fb0..5430bdb1 100644 --- a/nzbtomedia/autoProcess/autoProcessTV.py +++ b/nzbtomedia/autoProcess/autoProcessTV.py @@ -172,9 +172,10 @@ class autoProcessTV: return 0 # Success (as far as this script is concerned) if status == 0 and nzbtomedia.TRANSCODE == 1: # only transcode successful downlaods - result = transcoder.Transcode_directory(dirName) + result, newDirName = transcoder.Transcode_directory(dirName) if result == 0: logger.debug("SUCCESS: Transcoding succeeded for files in %s" % (dirName), section) + dirName = newDirName else: logger.warning("FAILED: Transcoding failed for files in %s" % (dirName), section) diff --git a/nzbtomedia/nzbToMediaConfig.py b/nzbtomedia/nzbToMediaConfig.py index 2eefeaca..ff9ead94 100644 --- a/nzbtomedia/nzbToMediaConfig.py +++ b/nzbtomedia/nzbToMediaConfig.py @@ -370,8 +370,14 @@ class ConfigObj(configobj.ConfigObj, Section): CFG_NEW[section][option] = value section = "Transcoder" - envKeys = ['TRANSCODE', 'DUPLICATE', 'IGNOREEXTENSIONS', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'OUTPUTAUDIOBITRATE', 'OUTPUTSUBTITLECODEC'] - cfgKeys = ['transcode', 'duplicate', 'ignoreExtensions', 'outputVideoExtension', 'outputVideoCodec', 'outputVideoPreset', 'outputVideoFramerate', 'outputVideoBitrate', 'outputAudioCodec', 'outputAudioBitrate', 'outputSubtitleCodec'] + envKeys = ['TRANSCODE', 'DUPLICATE', 'NICENESS', 'IGNOREEXTENSIONS', 'OUTPUTFASTSTART', 'OUTPUTVIDEOPATH', 'PROCESSOUTPUT', 'AUDIOLANGUAGE', 'ALLAUDIOLANGUAGES', 'SUBLANGUAGES', + 'ALLSUBLANGUAGES', 'EMBEDSUBS', 'BURNINSUBTITLE', 'EXTRACTSUBS', 'EXTERNALSUBDIR', 'OUTPUTDEFAULT', 'OUTPUTVIDEOEXTENSION', 'OUTPUTVIDEOCODEC', 'VIDEOCODECALLOW', + 'OUTPUTVIDEOPRESET', 'OUTPUTVIDEOFRAMERATE', 'OUTPUTVIDEOBITRATE', 'OUTPUTAUDIOCODEC', 'AUDIOCODECALLOW', 'OUTPUTAUDIOBITRATE', 'OUTPUTQUALITYPERCENT', + 'OUTPUTAUDIOTRACK2CODEC', 'AUDIOCODEC2ALLOW', 'OUTPUTAUDIOTRACK2BITRATE', 'OUTPUTAUDIOOTHERCODEC', 'AUDIOOTHERCODECALLOW', 'OUTPUTAUDIOOTHERBITRATE', 'OUTPUTSUBTITLECODEC'] + cfgKeys = ['transcode', 'duplicate', 'niceness', 'ignoreExtensions', 'outputFastStart', 'outputVideoPath', 'processOutput', 'audioLanguage', 'allAudioLanguages', 'subLanguages', + 'allSubLanguages', 'embedSubs', 'burnInSubtitle', 'extractSubs', 'externalSubDir', 'outputDefault', 'outputVideoExtension', 'outputVideoCodec', 'VideoCodecAllow', + 'outputVideoPreset', 'outputVideoFramerate', 'outputVideoBitrate', 'outputAudioCodec', 'AudioCodecAllow', 'outputAudioBitrate', 'outputQualityPercent', + 'outputAudioTrack2Codec', 'AudioCodec2Allow', 'outputAudioTrack2Bitrate', 'outputAudioOtherCodec', 'AudioOtherCodecAllow', 'outputAudioOtherBitrate', 'outputSubtitleCodec'] for index in range(len(envKeys)): key = 'NZBPO_' + envKeys[index] if os.environ.has_key(key): diff --git a/nzbtomedia/transcoder/transcoder.py b/nzbtomedia/transcoder/transcoder.py index ce6088f1..f06e4ff3 100644 --- a/nzbtomedia/transcoder/transcoder.py +++ b/nzbtomedia/transcoder/transcoder.py @@ -5,9 +5,10 @@ import subprocess import urllib2 import traceback import nzbtomedia +import json from subprocess import call from nzbtomedia import logger -from nzbtomedia.extractor import extractor +from nzbtomedia.nzbToMediaUtil import makeDir def isVideoGood(videofile): fileNameExt = os.path.basename(videofile) @@ -38,6 +39,296 @@ def isVideoGood(videofile): logger.error("FAILED: [%s] is corrupted!" % (fileNameExt), 'TRANSCODER') return False +def getVideoDetails(videofile): + video_details = {} + if not nzbtomedia.FFPROBE: + return video_details + command = [nzbtomedia.FFPROBE, '-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', videofile] + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + proc.wait() + video_details = json.loads(proc.stdout.read()) + return video_details + +def buildCommands(file, newDir): + video_details = getVideoDetails(file) + dir, name = os.path.split(file) + name, ext = os.path.splitext(name) + if ext == nzbtomedia.VEXTENSION and newDir == dir: # we need to change the name to prevent overwriting itself. + nzbtomedia.VEXTENSION = '-transcoded' + nzbtomedia.VEXTENSION # adds '-transcoded.ext' + + newfilePath = os.path.normpath(os.path.join(newDir, name) + nzbtomedia.VEXTENSION) + + map_cmd = [] + video_cmd = [] + audio_cmd = [] + sub_cmd = [] + other_cmd = [] + + if not video_details: # we couldn't read streams with ffprobe. Set defaults to try transcoding. + videoStreams = [] + audioStreams = [] + subStreams = [] + + map_cmd.extend(['-map', '0']) + if nzbtomedia.VCODEC: + video_cmd.extend(['-c:v', nzbtomedia.VCODEC]) + if nzbtomedia.VCODEC == 'libx264' and nzbtomedia.VPRESET: + video_cmd.extend(['-pre', nzbtomedia.VPRESET]) + else: + video_cmd.extend(['-c:v', 'copy']) + if nzbtomedia.VFRAMERATE: + video_cmd.extend(['-r', str(nzbtomedia.VFRAMERATE)]) + if nzbtomedia.VBITRATE: + video_cmd.extend(['-b:v', str(nzbtomedia.VBITRATE)]) + if nzbtomedia.VRESOLUTION: + video_cmd.extend(['-vf', 'scale=' + nzbtomedia.VRESOLUTION]) + + if nzbtomedia.ACODEC: + audio_cmd.extend(['-c:a', nzbtomedia.ACODEC]) + if nzbtomedia.ACODEC == 'aac': # Allow users to use the experimental AAC codec that's built into recent versions of ffmpeg + audio_cmd.extend(['-strict', '-2']) + else: + audio_cmd.extend(['-c:a', 'copy']) + if nzbtomedia.ABITRATE: + audio_cmd.extend(['-b:a', str(nzbtomedia.ABITRATE)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a', str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + + if nzbtomedia.OUTPUTSUBTITLECODEC and nzbtomedia.ALLOWSUBS: + sub_cmd.extend(['-c:s', nzbtomedia.SCODEC]) + elif nzbtomedia.ALLOWSUBS: # Not every subtitle codec can be used for every video container format! + sub_cmd.extend(['-c:s', 'copy']) + else: # http://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/subtitle_options + sub_cmd.extend('-sn') # Don't copy the subtitles over + + if nzbtomedia.OUTPUTFASTSTART: + other_cmd.extend(['-movflags', '+faststart']) + + else: + videoStreams = [item for item in video_details["streams"] if item["codec_type"] == "video"] + audioStreams = [item for item in video_details["streams"] if item["codec_type"] == "audio"] + subStreams = [item for item in video_details["streams"] if item["codec_type"] == "subtitle"] + + + for video in videoStreams: + req_tc = 0 + codec = video["codec_name"] + fr = video["avg_frame_rate"] + width = video["width"] + height = video["height"] + scale = nzbtomedia.VRESOLUTION + framerate = float(fr.split('/')[0])/float(fr.split('/')[1]) + vid_cmds = [] + if codec in nzbtomedia.VCODEC_ALLOW: + video_cmd.extend(['-c:v', 'copy']) + else: + video_cmd.extend(['-c:v', nzbtomedia.VCODEC]) + if nzbtomedia.VFRAMERATE and not (nzbtomedia.VFRAMERATE * 0.999 <= fr <= nzbtomedia.VFRAMERATE * 1.001): + video_cmd.extend(['-r', str(nzbtomedia.VFRAMERATE)]) + if scale: + w_scale = width/int(scale.split(':')[0]) + h_scale = height/int(scale.split(':')[1]) + if w_scale > h_scale: # widescreen, Scale by width only. + scale = scale.split(':')[0] + ":-1" + if w_scale != 1: + video_cmd.extend(['-vf', 'scale=' + scale]) + else: # lower or mathcing ratio, scale by height only. + scale = "-1:" + scale.split(':')[1] + if h_scale != 1: + video_cmd.extend(['-vf', 'scale=' + scale]) + map_cmd.extend(['-map', '0:' + str(video["index"])]) + break # Only one video needed + + used_audio = 0 + a_mapped = [] + if audioStreams: + audio1 = [ item for item in audioStreams if item["tags"]["language"] == nzbtomedia.ALANGUAGE ] + audio2 = [ item for item in audio1 if item["codec_name"] in nzbtomedia.ACODEC_ALLOW ] + audio3 = [ item for item in audioStreams if item["tags"]["language"] != nzbtomedia.ALANGUAGE ] + + if audio2: # right language and codec... + map_cmd.extend(['-map', '0:' + str(audio2[0]["index"])]) + a_mapped.extend([audio2[0]["index"]]) + bitrate = int(audio2[0]["bit_rate"])/1000 + audio_cmd.extend(['-c:a:' + str(used_audio), 'copy']) + if nzbtomedia.ABITRATE and not (nzbtomedia.ABITRATE * 0.9 < bitrate < nzbtomedia.ABITRATE * 1.1): + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + elif audio1: # right language wrong codec. + map_cmd.extend(['-map', '0:' + str(audio1[0]["index"])]) + a_mapped.extend([audio1[0]["index"]]) + audio_cmd.extend(['-c:a:' + str(used_audio), nzbtomedia.ACODEC]) + if nzbtomedia.ABITRATE: + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + elif audio3: # just pick the default audio track + map_cmd.extend(['-map', '0:' + str(audio3[0]["index"])]) + a_mapped.extend([audio3[0]["index"]]) + audio_cmd.extend(['-c:a:' + str(used_audio), nzbtomedia.ACODEC]) + if nzbtomedia.ABITRATE: + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + + if nzbtomedia.ACODEC2_ALLOW: + used_audio += 1 + audio4 = [ item for item in audio1 if item["codec_name"] in nzbtomedia.ACODEC2_ALLOW ] + if audio4: # right language and codec. + map_cmd.extend(['-map', '0:' + str(audio4[0]["index"])]) + a_mapped.extend([audio4[0]["index"]]) + bitrate = int(audio3[0]["bit_rate"])/1000 + audio_cmd.extend(['-c:a:' + str(used_audio), 'copy']) + if nzbtomedia.ABITRATE2 and not (nzbtomedia.ABITRATE2 * 0.9 < bitrate < nzbtomedia.ABITRATE2 * 1.1): + audio_cmd.extend(['-b:a' + str(used_audio), str(nzbtomedia.ABITRATE2)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + elif audio1: # right language wrong codec. + map_cmd.extend(['-map', '0:' + str(audio1[0]["index"])]) + a_mapped.extend([audio1[0]["index"]]) + audio_cmd.extend(['-c:a:' + str(used_audio), nzbtomedia.ACODEC2]) + if nzbtomedia.ABITRATE2: + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE2)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + elif audio3: # just pick the default audio track + map_cmd.extend(['-map', '0:' + str(audio3[0]["index"])]) + a_mapped.extend([audio3[0]["index"]]) + audio_cmd.extend(['-c:a:' + str(used_audio), nzbtomedia.ACODEC2]) + if nzbtomedia.ABITRATE2: + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE2)]) + if nzbtomedia.OUTPUTQUALITYPERCENT: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + + if nzbtomedia.AINCLUDE and audio3: # just pick the default audio track + for audio in audioStreams: + if audio["index"] in a_mapped: + continue + used_audio += 1 + map_cmd.extend(['-map', '0:' + str(audio["index"])]) + codec = audio["codec_name"] + bitrate = int(audio3[0]["bit_rate"])/1000 + if audio["codec_name"] in nzbtomedia.ACODEC3_ALLOW: + audio_cmd.extend(['-c:a:' + str(used_audio), 'copy']) + if nzbtomedia.ABITRATE3 and not (nzbtomedia.ABITRATE3 * 0.9 < bitrate < nzbtomedia.ABITRATE3 * 1.1): + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE3)]) + else: + audio_cmd.extend(['-c:a:' + str(used_audio), nzbtomedia.ACODEC3_ALLOW]) + if nzbtomedia.ABITRATE3: + audio_cmd.extend(['-b:a:' + str(used_audio), str(nzbtomedia.ABITRATE3)]) + if nzbtomedia.OUTPUTQUALITYPERCENT > 0: + audio_cmd.extend(['-q:a:' + str(used_audio), str(nzbtomedia.OUTPUTQUALITYPERCENT)]) + + s_mapped = [] + subs1 = [] + burnt = 0 + for lan in nzbtomedia.SLANGUAGES: + subs1 = [ item for item in subStreams if item["tags"]["language"] == lan ] + if nzbtomedia.BURN and not subs1 and not burnt: + for subfile in get_subs(file): + if lan in os.path.split(subfile)[1]: + video_cmd.extend(['-vf', 'subtitles=' + subfile]) + burnt = 1 + for sub in subs1: + if nzbtomedia.BURN and not burnt: + subloc = 0 + for index in range(len(subStreams)): + if sunStreams[index]["index"] == sub["index"]: + subloc = index + break + video_cmd.extend(['-vf', 'subtitles=' + file + ":si=" + subloc]) + burnt = 1 + if not nzbtomedia.ALLOWSUBS: + break + map_cmd.extend(['-map', '0:' + str(sub["index"])]) + s_mapped.extend([sub["index"]]) + + if nzbtomedia.SINCLUDE: + for sub in subStreams: + if not nzbtomedia.ALLOWSUBS: + break + if sub["index"] in s_mapped: + continue + map_cmd.extend(['-map', '0:' + str(sub["index"])]) + s_mapped.extend([sub["index"]]) + if not nzbtomedia.ALLOWSUBS: + sub_cmd.extend('-sn') + else: + if nzbtomedia.SCODEC: + sub_cmd.extend(['-c:s', nzbtomedia.SCODEC]) + else: + sub_cmd.extend(['-c:s', 'copy']) + + if nzbtomedia.OUTPUTFASTSTART: + other_cmd.extend(['-movflags', '+faststart']) + + command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', file] + + if nzbtomedia.SEMBED: + filenum = 1 + for subfile in get_subs(file): + command.extend(['-i', subfile]) + map_cmd.extend(['-map', n]) + n += 1 + + command.extend(map_cmd) + command.extend(video_cmd) + command.extend(audio_cmd) + command.extend(sub_cmd) + command.extend(other_cmd) + command.append(newfilePath) + if platform.system() != 'Windows': + command = ['nice', '-%d' % nzbtomedia.NICENESS] + command + return command + +def get_subs(file): + filepaths = [] + subExt = ['.srt', '.sub', '.idx'] + name = os.path.splitext(os.path.split(file)[1])[0] + for dirname, dirs, filenames in os.walk(dir): + for filename in filenames: + filepaths.extend([os.path.join(dirname, filename)]) + subfiles = [ item for item in filepaths if os.path.splitext(item)[1] in subExt and name in item ] + return subfiles + +def extract_subs(file, newfilePath, bitbucket): + video_details = getVideoDetails(file) + if not video_details: + return + subStreams = [item for item in video_details["streams"] if item["codec_type"] == "subtitle"] + if nzbtomedia.SUBSDIR: + subdir = nzbtomedia.SUBSDIR + else: + subdir = os.path.split(newfilePath)[0] + name = os.path.splitext(os.path.split(newfilePath)[1])[0] + for n in range(len(subStreams)): + sub = subStreams[n] + lan = sub["tags"]["language"] + outputFile = os.path.join(subdir, "%s(%s).srt" %(name, lan)) + if os.path.isfile(outputFile): + outputFile = os.path.join(subdir, "%s(%s)%s.srt" %(name, n, lan)) + command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', sub, '-vn', '-an', '-codec:s:' + str(n), 'srt', outputFile] + if platform.system() != 'Windows': + command = ['nice', '-%d' % nzbtomedia.NICENESS] + command + + logger.info("Extracting %s Subtitle from: %s" % (lan, file)) + cmd = "" + for item in command: + cmd = cmd + " " + item + logger.debug("calling command:%s" % (cmd)) + result = 1 # set result to failed in case call fails. + try: + result = call(command, stdout=bitbucket, stderr=bitbucket) + except: + logger.error("Extracting subtitles has failed") + + if result == 0: + logger.info("Extracting %s Subtitle from %s has succeeded" % (lan, file)) + else: + logger.error("Extracting subtitles has failed") + + def Transcode_directory(dirName): if platform.system() == 'Windows': bitbucket = open('NUL') @@ -49,59 +340,16 @@ def Transcode_directory(dirName): logger.info("Checking for files to be transcoded") final_result = 0 # initialize as successful + if nzbtomedia.OUTPUTVIDEOPATH: + newDir = nzbtomedia.OUTPUTVIDEOPATH + makeDir(newDir) + else: + newDir = dirName for file in nzbtomedia.listMediaFiles(dirName): - name, ext = os.path.splitext(file) - if ext in [i.replace(".","") for i in nzbtomedia.MEDIACONTAINER]: + if os.path.splitext(file)[1] in nzbtomedia.IGNOREEXTENSIONS: continue - if ext == nzbtomedia.OUTPUTVIDEOEXTENSION: # we need to change the name to prevent overwriting itself. - nzbtomedia.OUTPUTVIDEOEXTENSION = '-transcoded' + nzbtomedia.OUTPUTVIDEOEXTENSION # adds '-transcoded.ext' - - newfilePath = os.path.normpath(name + nzbtomedia.OUTPUTVIDEOEXTENSION) - - command = [nzbtomedia.FFMPEG, '-loglevel', 'warning', '-i', file, '-map', '0'] # -map 0 takes all input streams - if platform.system() != 'Windows': - command = ['nice', '-%d' % nzbtomedia.NICENESS] + command - - if len(nzbtomedia.OUTPUTVIDEOCODEC) > 0: - command.append('-c:v') - command.append(nzbtomedia.OUTPUTVIDEOCODEC) - if nzbtomedia.OUTPUTVIDEOCODEC == 'libx264' and nzbtomedia.OUTPUTVIDEOPRESET: - command.append('-pre') - command.append(nzbtomedia.OUTPUTVIDEOPRESET) - else: - command.append('-c:v') - command.append('copy') - if len(nzbtomedia.OUTPUTVIDEOFRAMERATE) > 0: - command.append('-r') - command.append(str(nzbtomedia.OUTPUTVIDEOFRAMERATE)) - if len(nzbtomedia.OUTPUTVIDEOBITRATE) > 0: - command.append('-b:v') - command.append(str(nzbtomedia.OUTPUTVIDEOBITRATE)) - if len(nzbtomedia.OUTPUTAUDIOCODEC) > 0: - command.append('-c:a') - command.append(nzbtomedia.OUTPUTAUDIOCODEC) - if nzbtomedia.OUTPUTAUDIOCODEC == 'aac': # Allow users to use the experimental AAC codec that's built into recent versions of ffmpeg - command.append('-strict') - command.append('-2') - else: - command.append('-c:a') - command.append('copy') - if len(nzbtomedia.OUTPUTAUDIOBITRATE) > 0: - command.append('-b:a') - command.append(str(nzbtomedia.OUTPUTAUDIOBITRATE)) - if nzbtomedia.OUTPUTFASTSTART > 0: - command.append('-movflags') - command.append('+faststart') - if nzbtomedia.OUTPUTQUALITYPERCENT > 0: - command.append('-q:a') - command.append(str(nzbtomedia.OUTPUTQUALITYPERCENT)) - if len(nzbtomedia.OUTPUTSUBTITLECODEC) > 0: # Not every subtitle codec can be used for every video container format! - command.append('-c:s') - command.append(nzbtomedia.OUTPUTSUBTITLECODEC) # http://en.wikibooks.org/wiki/FFMPEG_An_Intermediate_Guide/subtitle_options - else: - command.append('-sn') # Don't copy the subtitles over - command.append(newfilePath) - + command = buildCommands(file, newDir) + newfilePath = command[-1] try: # Try to remove the file that we're transcoding to just in case. (ffmpeg will return an error if it already exists for some reason) os.remove(newfilePath) except OSError, e: @@ -123,10 +371,23 @@ def Transcode_directory(dirName): if result == 0: logger.info("Transcoding of video %s to %s succeeded" % (file, newfilePath)) - if nzbtomedia.DUPLICATE == 0: # we get rid of the original file + if not nzbtomedia.DUPLICATE and os.path.isfile(newfilePath): # we get rid of the original file os.unlink(file) else: logger.error("Transcoding of video %s to %s failed" % (file, newfilePath)) # this will be 0 (successful) it all are successful, else will return a positive integer for failure. final_result = final_result + result - return final_result \ No newline at end of file + if nzbtomedia.SEXTRACT: + extract_subs(file, newfilePath, bitbucket) + if nzbtomedia.SUBSDIR: + for sub in get_subs(file): + name = os.path.splitext(os.path.split(file)[1])[0] + subname = os.path.split(sub)[1] + newname = os.path.splitext(os.path.split(newfilePath)[1])[0] + newpath = os.path.join(nzbtomedia.SUBSDIR, subname.replace(name, newname)) + if not os.path.isfile(newpath): + os.rename(sub, newpath) + + if not nzbtomedia.PROCESSOUTPUT and not nzbtomedia.DUPLICATE: # We postprocess the original files to CP/SB + newDir = dirName + return final_result, newDir \ No newline at end of file