def createVideoJob(self, sourceMediaFile=None): """ Creates a job to convert a video file to my own storage requirements @param sourceMediaFile Source MediaFile object @return Job instance to convert the video """ sourceVideoMediaStreams = sourceMediaFile.getVideoStreams() sourceAudioMediaStreams = sourceMediaFile.getAudioStreams() masterJob = None hanbrakeSourceMediaFile = copy.deepcopy(sourceMediaFile) hanbrakeDestinationMediaFile = MediaFile() ffmpegSourceMediaFile = MediaFile() ffmpegDestinationMediaFile = MediaFile() destinationHandbrakeVideoStreams = list() destinationHandbrakeAudioStreams = list() destinationHandbrakeVideoStream = None destinationHandbrakeAudioStream = None destinationFFMPEGVideoStreams = list() destinationFFMPEGAudioStreams = list() destinationFFMPEGVideoStream = None destinationFFMPEGAudioStream = None # Source video attributes sVWidth = None sVHeight = None sVCodecName = None sVCodecTag = None sVFramerateMin = None # Source audio attributes sACodecName = None sACodecTag = None sABitPerSample = None # Handbrake Destination video attributes dVHandbrakeCodecName = None dVHandbrakeStreamIndex = None dVHandbrakeWidth = None dVHandbrakeHeight = None dVHandbrakeQuality = None # Handbrake Destination audio attributes dAHandbrakeStreamIndex = None dAHandbrakeSampleRate = None dAHandbrakeCodecName = None # FFMPEG Destination video attributes dVFFMPEGCodecName = None # FFMPEG Destination audio attributes dAFFMPEGCodecName = None countSourceVideoStreams = len(sourceVideoMediaStreams) if countSourceVideoStreams == 1: vmsKey = sourceVideoMediaStreams.keys()[0] vms = sourceVideoMediaStreams[vmsKey] sVWidth = vms.getWidth() sVHeight = vms.getHeight() sVCodecName = vms.getCodecName() sVCodecTag = vms.getCodecTag() sVFramerateMin = vms.getFramerateMin() sACodecName = None sACodecTag = None sABitPerSample = None dVHandbrakeWidth = sVWidth dVHandbrakeHeight = sVHeight loggerCameraSourceType = "Not identified" skippedJobCreation = True skippedReason = "" countSourceAudioStreams = len(sourceAudioMediaStreams) if countSourceVideoStreams == 1: amsKey = sourceAudioMediaStreams.keys()[0] ams = sourceAudioMediaStreams[amsKey] sACodecName = ams.getCodecName() sACodecTag = ams.getCodecTag() sABitPerSample = ams.getBitPerSample() dAHandbrakeStreamIndex = "1" dAHandbrakeSampleRate = ams.getSampleRate() else: logger.warn("NOTE:" + sourceMediaFile.getFileName() + ": " + str(countSourceVideoStreams) + " audio stream found.") # Select appropriate destination media file convertion settings # Nikon D3100 if(sVWidth >= 1280 and sVHeight >= 720 and sVCodecName == "h264" and sVCodecTag == "0x31637661" and sACodecName == "pcm_s16le" and sACodecTag == "0x74776f73" and sABitPerSample == "16"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "25" dVHandbrakeWidth = 1280 dVHandbrakeHeight = 720 eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "Nikon D3100" skippedJobCreation = False # GoPro Silver 3+ elif(sVCodecName == "h264" and sVCodecTag == "0x31637661" and sACodecName == "aac" and sACodecTag == "0x6134706d"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "23" eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "GoPro 3+ Silver" skippedJobCreation = False # Canon Nexus 700 elif(sVWidth == 320 and sVHeight == 240 and sVCodecName == "mjpeg" and sVCodecTag == "0x47504a4d" and sACodecName == "pcm_u8" and sACodecTag == "0x0001" and sABitPerSample == "8"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "25" cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "Canon Nexus 700" skippedJobCreation = False # iPhone 3GS (NOT MBP 2007 iSight) elif(((sVWidth == 640 and sVHeight == 480) or (sVWidth == 480 and sVHeight == 360)) and sVCodecName == "h264" and sVCodecTag == "0x31637661" and sACodecName == "aac" and sACodecTag == "0x6134706d" and sABitPerSample == "0"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "30" eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC # quality=25 best quality=35 worst cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "iPhone 3GS" skippedJobCreation = False # MBP 2010 iSight elif(sVWidth == 320 and sVHeight == 240 and sVCodecName == "mjpeg" and sVCodecTag == "" and sACodecName == "pcm_u8" and sACodecTag == "" and sABitPerSample == "8"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "25" eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "Macbook Pro iSight 2010" skippedJobCreation = False # Unknown elif(sVWidth == 640 and sVHeight == 480 and sVCodecName == "mjpeg" and sVCodecTag == "" and sACodecName == "pcm_mulaw" and sACodecTag == "" and sABitPerSample == "8"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "25" eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "Unknown0" skippedJobCreation = False # Panasonic DMC FX-36 elif(sVWidth == 640 and sVHeight == 480 and sVCodecName == "mjpeg" and sVCodecTag == "0x6765706a" and sACodecName == "pcm_u8" and sACodecTag == "0x20776172" and sABitPerSample == "8"): evfH264 = HandbrakeCLGenerator.ENCODER_VIDEO_FORMAT_H264 dVHandbrakeCodecName = evfH264 dVHandbrakeStreamIndex = "0" dVHandbrakeQuality = "27" eafFAAC = HandbrakeCLGenerator.ENCODER_AUDIO_FORMAT_FAAC dAHandbrakeCodecName = eafFAAC # quality=25 best quality=35 worst cfMP4 = HandbrakeCLGenerator.CONTAINER_FORMAT_MP4 hanbrakeDestinationMediaFile.setContainerType(cfMP4) dVFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_VIDEO_FORMAT_COPY dAFFMPEGCodecName = FFMPEGCLGenerator.ENCODER_AUDIO_FORMAT_COPY loggerCameraSourceType = "Panasonic DMC FX-36" skippedJobCreation = False # Unknown 1 elif(sVCodecName == None and sVCodecTag == None and sACodecName == "aac" and sACodecTag == "0x6134706d" and sABitPerSample == "0"): # No need to re-encode skippedJobCreation = True skippedReason = "No need to re-encode" else: skippedJobCreation = True skippedReason = ("No suitable converter configuration found. " + "Missing a convertion case ? " + "New video file ?" ) if not skippedJobCreation: try: masterJob = OnSuccessOnlyConverterJob() # Convert with HandBrake as Job #1 hanbrakeSourceMediaFile.setFileName(util.escapePathForOSIndependentShell(hanbrakeSourceMediaFile.getFileName())) destinationHandbrakeVideoStream = VideoStream(codecName=dVHandbrakeCodecName, streamIndex=dVHandbrakeStreamIndex, framerateMin=sVFramerateMin, width=dVHandbrakeWidth, height=dVHandbrakeHeight, quality=dVHandbrakeQuality) destinationHandbrakeAudioStream = AudioStream(streamIndex=dAHandbrakeStreamIndex, sampleRate=dAHandbrakeSampleRate, codecName=dAHandbrakeCodecName) destinationHandbrakeVideoStreams.append(destinationHandbrakeVideoStream) destinationHandbrakeAudioStreams.append(destinationHandbrakeAudioStream) hanbrakeDestinationMediaFile.setVideoStreams(destinationHandbrakeVideoStreams) hanbrakeDestinationMediaFile.setAudioStreams(destinationHandbrakeAudioStreams) handbrakeDestinationFileName = sourceMediaFile.getFileName() + ".tmp." + str(hanbrakeDestinationMediaFile.getContainerType()) hanbrakeDestinationMediaFile.setFileName(util.escapePathForOSIndependentShell(handbrakeDestinationFileName)) handbrakeCLIBuilder = HandbrakeCLGenerator.createFrom(sourceMediaFile=hanbrakeSourceMediaFile, destinationMediaFile=hanbrakeDestinationMediaFile) handbrakeCLIBuilder.addLooseAnamorphic() handbrakeCLIBuilder.addVerbosity() handbrakeCLIRunner = CLRunner(shell=True) masterJob.addJob(ConverterJob(clibuilder=handbrakeCLIBuilder, clirunner=handbrakeCLIRunner)) loggerJobCreationRuntime.info("Handbrake cl:" + str(handbrakeCLIBuilder.tocl())) # Convert with FFMpeg as Job #2 destinationFFMPEGVideoStream = VideoStream(codecName=dVFFMPEGCodecName) destinationFFMPEGAudioStream = AudioStream(codecName=dAFFMPEGCodecName) ffmpegSourceMediaFile.setFileName(hanbrakeDestinationMediaFile.getFileName()) ffmpegDestinationMediaFile.setFileName(util.escapePathForOSIndependentShell(sourceMediaFile.getFileName())) destinationFFMPEGVideoStreams.append(destinationFFMPEGVideoStream) destinationFFMPEGAudioStreams.append(destinationFFMPEGAudioStream) ffmpegDestinationMediaFile.setVideoStreams(destinationFFMPEGVideoStreams) ffmpegDestinationMediaFile.setAudioStreams(destinationFFMPEGAudioStreams) ffmpegCLIBuilder = FFMPEGCLGenerator.createFrom(sourceMediaFile=ffmpegSourceMediaFile, destinationMediaFile=ffmpegDestinationMediaFile) ffmpegCLIBuilder.addOverwriteOutputFileWithoutAsking() ffmpegCLIRunner = CLRunner(shell=True) loggerJobCreationRuntime.info("ffmpeg cl:" + str(ffmpegCLIBuilder.tocl())) masterJob.addJob(ConverterJob(clibuilder=ffmpegCLIBuilder, clirunner=ffmpegCLIRunner)) # Delete temporary file as Job #3 masterJob.addJob(DeleteFileJob(filename=handbrakeDestinationFileName)) loggerJobCreationRuntime.info("Will delete file:" + str(handbrakeDestinationFileName)) loggerJobCreationSuccess.info("JOB_CREATION_SUCCESS:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType) except BaseException: loggerJobCreationFailed.exception("JOB_CREATION_FAILED:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType + "Exception :") else: loggerJobCreationSkipped.info("JOB_CREATION_SKIPPED:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType + " Reason: " + skippedReason) else: loggerJobCreationFailed.error("JOB_CREATION_FAILED:" + sourceMediaFile.getFileName() + ": Reason: 1 video stream expected. " + str(countSourceVideoStreams) + " found.") if not masterJob: masterJob = Job() # Created only if proper convert job not created return masterJob
def createImageJob(self, sourceMediaFile=None): """ Creates a job to convert image file to my own storage requirements @param sourceMediaFile Source MediaFile object @return Job instance to convert the image """ sourceImageStreams = sourceMediaFile.getImageStreams() masterJob = None backupDestinationMediaFile = MediaFile() convertDestinationMediaFile = MediaFile() destinationBakupImageStreams = list() destinationConvertImageStreams = list() # Source video attributes sIWidth = None sIHeight = None sIDPIX = None sIDPIY = None sIQuality = None # Handbrake Destination video attributes dIWidth = None dIHeight = None dIDPIX = None dIDPIY = None dIQuality = None countSourceImageStreams = len(sourceImageStreams) if countSourceImageStreams == 1: imsKey = sourceImageStreams.keys()[0] ims = sourceImageStreams[imsKey] sIWidth = ims.getWidth() sIHeight = ims.getHeight() sIDPIX = ims.getDensityX()[0] sIDPIY = ims.getDensityY()[0] sIQuality = ims.getQuality() loggerCameraSourceType = "Not identified" skippedJobCreation = True skippedReason = "" sIQuotientHeightWidth = float(float(sIHeight)/float(sIWidth)) # Select appropriate destination media file convertion settings # Unknown1 if(sIDPIX == 300 and sIDPIY == 300 and sIWidth >= 3508 and sIHeight >= 2480): if sIQuotientHeightWidth >= 1.0: sIHeight=3508 else: dIWidth=2480 dIQuality=95 loggerCameraSourceType = "Unknown1" skippedJobCreation = False # GoPro 3+ Silver - 10MP Wide Mode elif(sIDPIX == 72 and sIDPIY == 72 and sIWidth == 3680 and sIHeight == 2760): dIQuality=92 loggerCameraSourceType = "GoPro 3+ Silver - 10MP Wide Mode" skippedJobCreation = False # Unknown2 elif((sIWidth <= 2480 and sIHeight <= 3508) or (sIDPIX <=300 and sIDPIY <=300)): # No need to re-encode skippedJobCreation = True skippedReason = "No need to re-encode" else: skippedJobCreation = True skippedReason = "No suitable converter configuration found. Missing a convertion case ? New image file ?" if not skippedJobCreation: try: masterJob = OnSuccessOnlyConverterJob() # Backup file as Job #1 sourceBackupFileName = sourceMediaFile.getFileName() destinationBackupFileName = str(sourceBackupFileName) + ".backup" destinationBackupMediaFile = MediaFile() destinationBackupMediaFile.setFileName(destinationBackupFileName) copyFileJob = CopyFileJob(sourceFileName=sourceMediaFile.getFileName(), destinationFileName=destinationBackupMediaFile.getFileName()) masterJob.addJob(copyFileJob) loggerJobCreationRuntime.info("Will backup file: " + str(sourceBackupFileName) + " to " + str(destinationBackupFileName)) # Convert with ImageMagick's mogrity tool as Job #2 convertSourceMediaFile = MediaFile() convertSourceMediaFile.setFileName(util.escapePathForOSIndependentShell(destinationBackupFileName)) convertDestinationFileName = sourceMediaFile.getFileName() convertDestinationMediaFile.setFileName(util.escapePathForOSIndependentShell(convertDestinationFileName)) destinationConvertImageStream = ImageStream(filename=convertDestinationFileName, width=dIWidth, height=sIHeight, quality=dIQuality, densityX=dIDPIX, densityY=dIDPIY) destinationConvertImageStreams.append(destinationConvertImageStream) convertDestinationMediaFile.setImageStreams(destinationConvertImageStreams) convertCLIBuilder = ConvertCLGenerator.createResizeJobFrom(sourceMediaFile=convertSourceMediaFile, destinationMediaFile=convertDestinationMediaFile) convertCLIRunner = CLRunner(shell=True) masterJob.addJob(ConverterJob(clibuilder=convertCLIBuilder, clirunner=convertCLIRunner)) loggerJobCreationRuntime.info("convert cl:" + str(convertCLIBuilder.tocl())) # Delete backup file as Job #3 masterJob.addJob(DeleteFileJob(filename=destinationBackupMediaFile.getFileName())) loggerJobCreationRuntime.info("Will delete file:" + str(destinationBackupMediaFile.getFileName())) loggerJobCreationSuccess.info("JOB_CREATION_SUCCESS:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType) except BaseException: loggerJobCreationFailed.exception("JOB_CREATION_FAILED:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType + "Exception :") else: loggerJobCreationSkipped.info("JOB_CREATION_SKIPPED:" + sourceMediaFile.getFileName() + ": Type:" + loggerCameraSourceType + " Reason: " +skippedReason) else: loggerJobCreationFailed.error("JOB_CREATION_FAILED:" + sourceMediaFile.getFileName() + ": Reason: 1 video stream expected. " + str(countSourceVideoStreams) + " found.") if not masterJob: masterJob = Job() # Created only if proper convert job not created return masterJob