You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
7.8 KiB
249 lines
7.8 KiB
from typing import Optional
|
|
from minfo import MediaInfo
|
|
from pathlib import Path
|
|
|
|
class Configuration:
|
|
def __init__(self):
|
|
pass
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"IsDvdNavDisabled": False,
|
|
"EnableQuickSyncDecoding": False,
|
|
"UseQSVDecodeForNonQSVEnc": False,
|
|
"ScalingMode": 0,
|
|
"PreviewScanCount": 10,
|
|
"Verbosity": 1,
|
|
"MinScanDuration": 10,
|
|
"SaveLogToCopyDirectory": False,
|
|
"SaveLogWithVideo": False,
|
|
"SaveLogCopyDirectory": "",
|
|
"RemoteServiceEnabled": False,
|
|
"RemoteServicePort": 0,
|
|
"EnableVceEncoder": True,
|
|
"EnableNvencEncoder": False,
|
|
"EnableQsvEncoder": False
|
|
}
|
|
|
|
class Statistics:
|
|
def __init__(self):
|
|
pass
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"StartTime": "0001-01-01T00:00:00",
|
|
"StartTimeDisplay": "Not Available",
|
|
"EndTime": "0001-01-01T00:00:00",
|
|
"EndTimeDisplay": "",
|
|
"PausedDuration": "00:00:00",
|
|
"PausedDisplay": "",
|
|
"Duration": "00:00:00",
|
|
"DurationDisplay": "",
|
|
"FinalFileSizeInMegaBytes": 0,
|
|
"FileSizeDisplay": "",
|
|
"IsNotifying": True
|
|
}
|
|
|
|
class AllowedPassthruOptions:
|
|
def __init__(self):
|
|
pass
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"AudioAllowAACPass": True,
|
|
"AudioAllowAC3Pass": True,
|
|
"AudioAllowDTSHDPass": True,
|
|
"AudioAllowDTSPass": True,
|
|
"AudioAllowMP3Pass": True,
|
|
"AudioAllowTrueHDPass": True,
|
|
"AudioAllowFlacPass": True,
|
|
"AudioAllowEAC3Pass": True,
|
|
"AudioEncoderFallback": 5,
|
|
"AllowedPassthruOptions": [
|
|
13,
|
|
8,
|
|
11,
|
|
10,
|
|
14,
|
|
12,
|
|
18,
|
|
9
|
|
]
|
|
}
|
|
|
|
class AudioTrack:
|
|
def __init__(self, minfo: MediaInfo):
|
|
self.minfo = minfo
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"DRC": 0.0,
|
|
"Gain": 0,
|
|
"Encoder": 7,
|
|
"SampleRate": 0.0,
|
|
"EncoderRateType": 0,
|
|
"Bitrate": 160,
|
|
"Quality": -1.0,
|
|
"ScannedTrack": {
|
|
"TrackNumber": 1,
|
|
"Language": self.minfo.tracks[0].language,
|
|
# "LanguageCode": "und",
|
|
"Name": self.minfo.tracks[0].name,
|
|
#"Codec": 65536,
|
|
# aac is 65536
|
|
# mp3 is 524288
|
|
#"SampleRate": 32000,
|
|
#"Bitrate": 32002,
|
|
#"ChannelLayout": 4
|
|
},
|
|
"IsNotifying": True
|
|
}
|
|
|
|
class Chapters:
|
|
def __init__(self, minfo: MediaInfo):
|
|
self.minfo = minfo
|
|
|
|
def as_dict(self):
|
|
return [
|
|
{
|
|
"ChapterNumber": index + 1,
|
|
"Duration": c.duration, # self.mediainfo.duration,
|
|
"ChapterName": c.name, # "Chapter 1",
|
|
"IsNotifying": True
|
|
} for index, c in enumerate(self.minfo.menu.items)
|
|
]
|
|
|
|
class Task:
|
|
def __init__(self, path: Path, destination: Path):
|
|
self.path = path
|
|
self.destination = destination / (path.name.rsplit(".", 1)[0] + '.m4v')
|
|
self.allowed_passthru_options = AllowedPassthruOptions()
|
|
self.__mediainfo: Optional[MediaInfo] = None
|
|
self.__audio_track: Optional[AudioTrack] = None
|
|
|
|
@property
|
|
def mediainfo(self):
|
|
if not self.__mediainfo:
|
|
self.__mediainfo = MediaInfo()
|
|
self.__mediainfo.load_file(self.path)
|
|
return self.__mediainfo
|
|
|
|
@property
|
|
def audio_track(self):
|
|
if not self.__audio_track:
|
|
self.__audio_track = AudioTrack(self.mediainfo)
|
|
return self.__audio_track
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"Source": str(self.path),
|
|
"Title": 1,
|
|
"Angle": 1,
|
|
"PointToPointMode": 0,
|
|
"StartPoint": 1,
|
|
"EndPoint": len(self.mediainfo.menu.items),
|
|
"Destination": str(self.destination),
|
|
"OutputFormat": 0,
|
|
"OptimizeMP4": False,
|
|
"IPod5GSupport": False,
|
|
"AlignAVStart": True,
|
|
"Width": self.mediainfo.resolution.width,
|
|
"Height": self.mediainfo.resolution.height,
|
|
"Cropping": {
|
|
"Top": 0,
|
|
"Bottom": 0,
|
|
"Left": 0,
|
|
"Right": 0
|
|
},
|
|
"HasCropping": False,
|
|
"Anamorphic": 4,
|
|
"DisplayWidth": self.mediainfo.display_width,
|
|
"KeepDisplayAspect": self.mediainfo.keep_display_aspect,
|
|
"PixelAspectX": int(self.mediainfo.pixel_aspect_ratio.x),
|
|
"PixelAspectY": int(self.mediainfo.pixel_aspect_ratio.y),
|
|
"Modulus": 2,
|
|
"DeinterlaceFilter": 2,
|
|
"DeinterlacePreset": {
|
|
"Name": "Default",
|
|
"ShortName": "default"
|
|
},
|
|
"CombDetect": 2,
|
|
"CustomDeinterlaceSettings": "",
|
|
"CustomCombDetect": "",
|
|
"Detelecine": 0,
|
|
"CustomDetelecine": "",
|
|
"Denoise": 0,
|
|
"DenoisePreset": 5,
|
|
"DenoiseTune": 0,
|
|
"CustomDenoise": "",
|
|
"Grayscale": False,
|
|
"Rotation": 0,
|
|
"FlipVideo": False,
|
|
"Sharpen": 0,
|
|
"SharpenPreset": {
|
|
"DisplayName": "Medium",
|
|
"Key": "medium"
|
|
},
|
|
"SharpenTune": {
|
|
"DisplayName": "None",
|
|
"Key": "none"
|
|
},
|
|
"SharpenCustom": "",
|
|
"DeblockPreset": {
|
|
"DisplayName": "Off",
|
|
"Key": "off"
|
|
},
|
|
"DeblockTune": {
|
|
"DisplayName": "Medium (8x8)",
|
|
"Key": "medium"
|
|
},
|
|
"CustomDeblock": "strength=strong:thresh=20:blocksize=8",
|
|
"VideoEncodeRateType": 1,
|
|
"VideoEncoder": 13,
|
|
"VideoProfile": {
|
|
"DisplayName": "Main",
|
|
"ShortName": "main"
|
|
},
|
|
"VideoLevel": {
|
|
"DisplayName": "Auto",
|
|
"ShortName": "auto"
|
|
},
|
|
"VideoPreset": {
|
|
"DisplayName": "Quality",
|
|
"ShortName": "quality"
|
|
},
|
|
"VideoTunes": [],
|
|
"ExtraAdvancedArguments": "",
|
|
"FramerateMode": 1,
|
|
"Quality": 22.0,
|
|
"VideoBitrate": self.mediainfo.output_bitrate,
|
|
"TwoPass": False,
|
|
"TurboFirstPass": False,
|
|
"Framerate": self.mediainfo.framerate,
|
|
"AudioTracks": [
|
|
self.audio_track.as_dict()
|
|
],
|
|
"AllowedPassthruOptions": self.allowed_passthru_options.as_dict(),
|
|
"SubtitleTracks": [],
|
|
"IncludeChapterMarkers": len(self.mediainfo.menu.items) > 1,
|
|
"ChapterNames": Chapters(self.mediainfo).as_dict(),
|
|
"MetaData": {},
|
|
"IsPreviewEncode": False
|
|
}
|
|
|
|
class QueueItem:
|
|
def __init__(self, path: Path, destination: Path):
|
|
self.path = path
|
|
self.task = Task(path, destination)
|
|
self.configuration = Configuration()
|
|
self.statistics = Statistics()
|
|
|
|
def as_dict(self):
|
|
return {
|
|
"ScannedSourcePath": str(self.path),
|
|
"Status": 0,
|
|
"Task": self.task.as_dict(),
|
|
"Configuration": self.configuration.as_dict(),
|
|
"Statistics": self.statistics.as_dict()
|
|
}
|