Unit3DwebUp 0.0.14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. config/__init__.py +4 -0
  2. config/api_data.py +28 -0
  3. config/constants.py +34 -0
  4. config/host_data.py +47 -0
  5. config/itt.py +154 -0
  6. config/logger.py +37 -0
  7. config/settings.py +212 -0
  8. config/sis.py +137 -0
  9. config/tags.py +395 -0
  10. config/trackers.py +47 -0
  11. external/__init__.py +0 -0
  12. external/async_http_client_service.py +48 -0
  13. external/websocket.py +41 -0
  14. models/__init__.py +0 -0
  15. models/interfaces.py +39 -0
  16. models/keywords.py +13 -0
  17. models/media.py +597 -0
  18. models/media_info.py +142 -0
  19. models/movie.py +287 -0
  20. models/tv.py +266 -0
  21. models/tvdb_search.py +102 -0
  22. models/videos.py +26 -0
  23. repositories/__init__.py +0 -0
  24. repositories/db_online.py +82 -0
  25. repositories/interfaces.py +59 -0
  26. repositories/job_repos.py +166 -0
  27. repositories/media_info_factory.py +28 -0
  28. services/__init__.py +0 -0
  29. services/auto_async_service.py +237 -0
  30. services/create_torrent_service.py +94 -0
  31. services/interfaces.py +72 -0
  32. services/itt_tracker_helper.py +463 -0
  33. services/itt_tracker_service.py +85 -0
  34. services/lifespan_service.py +58 -0
  35. services/media_service.py +114 -0
  36. services/tags_service.py +389 -0
  37. services/tmdb.py +246 -0
  38. services/torrent_client_service.py +92 -0
  39. services/torrent_service.py +107 -0
  40. services/tvdb.py +65 -0
  41. services/utility.py +433 -0
  42. services/video_service.py +356 -0
  43. unit3dwebup-0.0.14.dist-info/METADATA +191 -0
  44. unit3dwebup-0.0.14.dist-info/RECORD +53 -0
  45. unit3dwebup-0.0.14.dist-info/WHEEL +5 -0
  46. unit3dwebup-0.0.14.dist-info/entry_points.txt +2 -0
  47. unit3dwebup-0.0.14.dist-info/top_level.txt +6 -0
  48. use_case/__init__.py +0 -0
  49. use_case/make_torrent_usecase.py +67 -0
  50. use_case/process_all_usecase.py +43 -0
  51. use_case/scan_media_usecase.py +133 -0
  52. use_case/seed_usecase.py +117 -0
  53. use_case/upload_usecase.py +77 -0
config/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from config.itt import itt_data
2
+ from config.sis import sis_data
3
+
4
+ tracker_list = {'ITT': itt_data, 'SIS': sis_data}
config/api_data.py ADDED
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Same as the old code 08.21
4
+ from config.settings import get_settings
5
+
6
+ settings = get_settings()
7
+
8
+ # Get data based on tracker name. For example itt e sis
9
+ trackers_api_data = {
10
+ 'ITT':
11
+ {
12
+ "url": settings.tracker.ITT_URL,
13
+ "api_key": settings.tracker.ITT_APIKEY,
14
+ "pass_key": settings.tracker.ITT_PID,
15
+ "announce": f"{settings.tracker.ITT_URL}/announce/{settings.tracker.ITT_PID}",
16
+ "source": "ItaTorrents",
17
+ }
18
+ ,
19
+ 'SIS':
20
+ {
21
+ "url": settings.tracker.SIS_URL,
22
+ "api_key": settings.tracker.SIS_APIKEY,
23
+ "pass_key": settings.tracker.SIS_PID,
24
+ "announce": f"{settings.tracker.SIS_URL}/announce/{settings.tracker.SIS_PID}",
25
+ "source": "ShareIsland",
26
+ }
27
+
28
+ }
config/constants.py ADDED
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ from enum import IntEnum
3
+
4
+
5
+ class MediaStatus(IntEnum):
6
+ """
7
+ It tracks the status during the creation of a media file
8
+ """
9
+ INDEXED = 0
10
+
11
+ # Searching tmdb,tvdb,imdb
12
+ DB_IDENTIFIED = 1
13
+ DB_NOT_IDENTIFIED = 10
14
+ DB_ERROR = 11
15
+
16
+ # When extracting the screenshots from the video file
17
+ VIDEO_READY = 2
18
+ VIDEO_ERROR = 20
19
+
20
+ # When uploading raw data to the image host
21
+ DESCRIPTION_READY = 3
22
+ DESCRIPTION_ERROR = 30
23
+
24
+ # When generating the torrent file *.torrent
25
+ TORRENT_GENERATED = 4
26
+ TORRENT_ERROR = 40
27
+
28
+ # When uploading torrent files to the tracker
29
+ TRACKER_UPLOADED = 5
30
+ TRACKER_NOT_UPLOADED = 50
31
+
32
+ # When seeding one or more torrent files
33
+ TORRENT_SEED = 7
34
+ TORRENT_SEED_ERROR = 70
config/host_data.py ADDED
@@ -0,0 +1,47 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from config.settings import get_settings
4
+
5
+ settings = get_settings()
6
+
7
+ # Same as the old 0.8.21. Set the priority based on the config file
8
+ # TODO : host rotation on failure is not implemented yet
9
+ master_uploaders = ['ImgBB', 'PtScreens', 'LensDump', 'ImgFi', 'PassIMA', 'ImaRide', 'Freeimage']
10
+
11
+ upload_hosts = {
12
+ "ImgBB": {
13
+ "url": "https://api.imgbb.com/1/upload",
14
+ "data": {"key": settings.tracker.IMGBB_KEY, "fieldname": "name"},
15
+ "fieldname": "image"
16
+ },
17
+ "Freeimage": {
18
+ "url": "https://freeimage.host/api/1/upload",
19
+ "data": {"key": settings.tracker.FREE_IMAGE_KEY, "fieldname": "name"},
20
+ "fieldname": "image"
21
+ },
22
+ "PtScreens": {
23
+ "url": "https://ptscreens.com/api/1/upload",
24
+ "data": {"key": settings.tracker.PTSCREENS_KEY, "fieldname": "title"},
25
+ "fieldname": "source"
26
+ },
27
+ "LensDump": {
28
+ "url": "https://lensdump.com/api/1/upload",
29
+ "data": {"key": settings.tracker.LENSDUMP_KEY, "fieldname": "title"},
30
+ "fieldname": "source"
31
+ },
32
+ "ImgFi": {
33
+ "url": "https://imgfi.com/api/1/upload",
34
+ "data": {"key": settings.tracker.IMGFI_KEY, "fieldname": "title"},
35
+ "fieldname": "source"
36
+ },
37
+ "PassIMA": {
38
+ "url": "https://passtheima.ge/api/1/upload",
39
+ "data": {"key": settings.tracker.PASSIMA_KEY, "title": "name"},
40
+ "fieldname": "source"
41
+ },
42
+ "ImaRide": {
43
+ "url": "https://www.imageride.net/api/1/upload",
44
+ "data": {"key": settings.tracker.IMARIDE_KEY, "fieldname": "title"},
45
+ "fieldname": "source"
46
+ }
47
+ }
config/itt.py ADDED
@@ -0,0 +1,154 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # List of constants pointing to the itt tracker
4
+ # TODO: Add automode to extract these constants?
5
+ itt_data = {
6
+ "CATEGORY": {"movie": 1,
7
+ "series": 2,
8
+ "edicola": 6,
9
+ "game": 4},
10
+
11
+ "FREELECH": {"size20": 100,
12
+ "size15": 75,
13
+ "size10": 50,
14
+ "size5": 25},
15
+
16
+ "TYPE_ID": {"full-disc": 1,
17
+ "remux": 2,
18
+ "bdremux": 2,
19
+ "vh": 2,
20
+ "untouched": 2,
21
+ "bd-untouched": 2,
22
+ "encode": 3,
23
+ "bluray": 3,
24
+ "fullhd": 3,
25
+ "hevc": 3,
26
+ "hdrip": 3,
27
+ "vu": 2,
28
+ "web-dl": 4,
29
+ "webdl": 4,
30
+ "web": 4,
31
+ "web-dlmux": 4,
32
+ "webrip": 5,
33
+ "hdtv": 6,
34
+ "mac": 12,
35
+ "macos": 12,
36
+ "windows": 13,
37
+ "pc": 13,
38
+ "cinema-md": 14,
39
+ "hdts": 14,
40
+ "wrs": 14,
41
+ "md": 14,
42
+ "altro": 15,
43
+ "pdf": 16,
44
+ "nintendo": 17,
45
+ "nsw": 17,
46
+ "ps4": 18,
47
+ "psn": 18,
48
+ "epub": 19,
49
+ "mp4": 20,
50
+ "pack": 22,
51
+ "avi": 23,
52
+ "dvdrip": 24,
53
+ "bdrip": 25,
54
+ "webmux": 26,
55
+ "dlmux": 27,
56
+ "bdmux": 29,
57
+ "3d": 32,
58
+ "cbr-cbz": 33,
59
+ "ps5": 35,
60
+ "psvr": 35,
61
+ },
62
+ "TYPE_ID_AUDIO": {"flac": 7,
63
+ "alac": 8,
64
+ "ac3": 9,
65
+ "aac": 10,
66
+ "mp3": 11,
67
+ },
68
+ "TAGS": {
69
+ "SD": 1,
70
+ "HD": 0,
71
+ },
72
+ "RESOLUTION": {
73
+ "4320p": 1,
74
+ "2160p": 2,
75
+ "1080p": 3,
76
+ "1080i": 4,
77
+ "720p": 5,
78
+ "576p": 6,
79
+ "576i": 7,
80
+ "480p": 8,
81
+ "480i": 9,
82
+ "altro": 10,
83
+ },
84
+ "CODEC": [
85
+ "h261",
86
+ "h262",
87
+ "h263",
88
+ "h264",
89
+ "x264",
90
+ "x265",
91
+ "avc",
92
+ "h265",
93
+ "hevc",
94
+ "vp8",
95
+ "vp9",
96
+ "av1",
97
+ "mpeg-1",
98
+ "mpeg-4",
99
+ "wmv",
100
+ "theora",
101
+ "divx",
102
+ "xvid",
103
+ "prores",
104
+ "dnxhd",
105
+ "cinepak",
106
+ "indeo",
107
+ "dv",
108
+ "ffv1",
109
+ "sorenson",
110
+ "rv40",
111
+ "cineform",
112
+ "huffyuv",
113
+ "mjpeg",
114
+ "lagarith",
115
+ "msu",
116
+ "rle",
117
+ "dirac",
118
+ "wmv3",
119
+ "vorbis",
120
+ "smpte",
121
+ "mjpeg",
122
+ "ffvhuff",
123
+ "v210",
124
+ "yuv4:2:2",
125
+ "yuv4:4:4",
126
+ "hap",
127
+ "sheervideo",
128
+ "ut",
129
+ "quicktime",
130
+ "rududu",
131
+ "h.266",
132
+ "vvc",
133
+ "mjpeg 4:2:0",
134
+ "h.263+",
135
+ "h.263++",
136
+ "vp4",
137
+ "vp5",
138
+ "vp6",
139
+ "vp7",
140
+ "vp8",
141
+ "vp9",
142
+ "vp10",
143
+ "vp11",
144
+ "vp12",
145
+ "vp3",
146
+ "vp2",
147
+ "vp1",
148
+ "amv",
149
+ "daala",
150
+ "gecko",
151
+ "nvenc",
152
+ "bluray",
153
+ ],
154
+ }
config/logger.py ADDED
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import logging
4
+ import sys
5
+
6
+ COLORS = {
7
+ logging.DEBUG: "\033[36m", # -> cyano
8
+ logging.INFO: "\033[32m", # -> green
9
+ logging.WARNING: "\033[33m", # -> yellow
10
+ logging.ERROR: "\033[31m", # -> red
11
+ logging.CRITICAL: "\033[41m", # -> red background
12
+ }
13
+
14
+ RESET = "\033[0m"
15
+
16
+ class ColorFormatter(logging.Formatter):
17
+
18
+ # Called by the handler
19
+ def format(self, record):
20
+ color = COLORS.get(record.levelno, "")
21
+ message = super().format(record)
22
+ return f"{color}{message}{RESET}"
23
+
24
+
25
+ # /// Attempt to create a dedicated logger for Docker....
26
+ def get_logger(name: str = "app_logger") -> logging.Logger:
27
+ logger = logging.getLogger(name)
28
+
29
+ if not logger.hasHandlers():
30
+ logger.setLevel(logging.INFO)
31
+ handler = logging.StreamHandler(sys.stdout)
32
+ formatter = ColorFormatter("[%(levelname)s] %(name)s: %(message)s")
33
+ handler.setFormatter(formatter) # Custom formatter
34
+ logger.addHandler(handler)
35
+ return logger
36
+
37
+
config/settings.py ADDED
@@ -0,0 +1,212 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ from functools import lru_cache
4
+ from enum import Enum
5
+ from pathlib import Path
6
+
7
+ from pydantic import BaseModel, field_validator, model_validator, HttpUrl, Field, ValidationError
8
+ from pydantic_settings import BaseSettings, SettingsConfigDict
9
+ from config.logger import get_logger
10
+
11
+
12
+ # /// Class to help avoid typos...
13
+ class TorrentClient(str, Enum):
14
+ qbittorrent = "qbittorrent"
15
+ transmission = "transmission"
16
+ rtorrent = "rtorrent"
17
+
18
+
19
+ # /// Check for missing value
20
+ class BaseConfigModel(BaseModel):
21
+
22
+ @field_validator("*", mode="before")
23
+ @classmethod
24
+ def empty_to_none(cls, v):
25
+ if v == "":
26
+ return None
27
+ return v
28
+
29
+
30
+ # /// version
31
+ class Unit3DwebUp(BaseConfigModel):
32
+ VERSION: str = "build"
33
+
34
+
35
+ # /// TRACKER CONFIG
36
+ class TrackerConfig(BaseConfigModel):
37
+ ITT_URL: HttpUrl
38
+ ITT_APIKEY: str = None
39
+ ITT_PID: str | None = None
40
+ SIS_URL: HttpUrl
41
+ SIS_APIKEY: str | None = None
42
+ SIS_PID: str | None = None
43
+ MULTI_TRACKER: list[str]
44
+ TMDB_APIKEY: str = None
45
+ TVDB_APIKEY: str = None
46
+ IMGBB_KEY: str = None
47
+ FREE_IMAGE_KEY: str | None = None
48
+ LENSDUMP_KEY: str | None = None
49
+ PTSCREENS_KEY: str | None = None
50
+ IMGFI_KEY: str | None = None
51
+ PASSIMA_KEY: str | None = None
52
+ IMARIDE_KEY: str | None = None
53
+ YOUTUBE_KEY: str | None = None
54
+ IGDB_CLIENT_ID: str | None = None
55
+ IGDB_ID_SECRET: str | None = None
56
+
57
+ @field_validator("MULTI_TRACKER", mode="before")
58
+ @classmethod
59
+ def parse_multi_tracker(cls, v):
60
+ if isinstance(v, str):
61
+ return [x.strip() for x in v.split(",") if x.strip()]
62
+ return v
63
+
64
+ @field_validator("*")
65
+ @classmethod
66
+ def validate_api_keys(cls, v, info):
67
+ if info.field_name.endswith("_KEY") or "APIKEY" in info.field_name:
68
+ if v is not None and len(v) < 5:
69
+ raise ValueError(f"{info.field_name} too short")
70
+ return v
71
+
72
+
73
+ # /// TORRENT CLIENT CONFIG
74
+ class TorrentClientConfig(BaseConfigModel):
75
+ # Default value when the variable is commented out
76
+ QBIT_USER: str = "admin"
77
+ QBIT_PASS: str = "admin"
78
+ QBIT_HOST: str = "http://127.0.0.1"
79
+ QBIT_PORT: int = 8080
80
+ SHARED_QBIT_PATH: str = "/tmp"
81
+
82
+ TRASM_USER: str = "admin"
83
+ TRASM_PASS: str = "admin"
84
+ TRASM_HOST: str = "http://127.0.0.1"
85
+ TRASM_PORT: int = 9091
86
+ SHARED_TRASM_PATH: str = "/tmp"
87
+
88
+ RTORR_USER: str = "admin"
89
+ RTORR_PASS: str = "admin"
90
+ RTORR_HOST: str = "http://127.0.0.1"
91
+ RTORR_PORT: int = 5000
92
+ SHARED_RTORR_PATH: str = "/tmp"
93
+
94
+ TORRENT_CLIENT: TorrentClient = "qbittorrent"
95
+ TAG: str = "TAG1"
96
+
97
+ @field_validator("QBIT_PORT", "TRASM_PORT", "RTORR_PORT")
98
+ @classmethod
99
+ def validate_ports(cls, v):
100
+ if not 1 <= v <= 65535:
101
+ raise ValueError("invalid port range")
102
+ return v
103
+
104
+ @model_validator(mode="after")
105
+ def validate_selected_client(self):
106
+ if self.TORRENT_CLIENT == TorrentClient.qbittorrent:
107
+ if not self.QBIT_HOST:
108
+ raise ValueError("qbittorrent selected but no host has been configured")
109
+ if self.TORRENT_CLIENT == TorrentClient.transmission:
110
+ if not self.TRASM_HOST:
111
+ raise ValueError("transmission selected but no host has been configured")
112
+ if self.TORRENT_CLIENT == TorrentClient.rtorrent:
113
+ if not self.RTORR_HOST:
114
+ raise ValueError("rtorrent selected but no host has been configured")
115
+ return self
116
+
117
+
118
+ # /// USER PREFERENCES
119
+ class UserPreferences(BaseConfigModel):
120
+ RELEASER_SIGN: str = ""
121
+ TAG_POSITION_MOVIE: list[str]
122
+ TAG_POSITION_SERIE: list[str]
123
+ PTSCREENS_PRIORITY: int = 0
124
+ LENSDUMP_PRIORITY: int = 1
125
+ FREE_IMAGE_PRIORITY: int = 2
126
+ IMGBB_PRIORITY: int = 3
127
+ IMGFI_PRIORITY: int = 4
128
+ PASSIMA_PRIORITY: int = 5
129
+ IMARIDE_PRIORITY: int = 6
130
+
131
+ NUMBER_OF_SCREENSHOTS: int = 4
132
+ YOUTUBE_CHANNEL_ENABLE: bool = False
133
+ DUPLICATE_ON: bool = False # Todo Not yet implemented
134
+ SKIP_DUPLICATE: bool = False #
135
+ SKIP_YOUTUBE: bool = False
136
+ SIZE_TH: int = 50
137
+ WATCHER_INTERVAL: int = 60
138
+ WATCHER_PATH: str | None = None
139
+ WATCHER_DESTINATION_PATH: str | None = None
140
+ TORRENT_ARCHIVE_PATH: str = None
141
+ SCAN_PATH: str = None
142
+ COMPRESS_SCSHOT: int = 4
143
+ TORRENT_COMMENT: str | None = "no_comment"
144
+ PREFERRED_LANG: str | None = "all"
145
+ ANON: bool = False
146
+ WEBP_ENABLED: bool = False
147
+ PERSONAL_RELEASE: bool = False
148
+ FAST_LOAD: int = 0
149
+
150
+ @field_validator("WATCHER_INTERVAL")
151
+ @classmethod
152
+ def validate_interval(cls, v):
153
+ if v < 5:
154
+ raise ValueError("WATCHER_INTERVAL too low")
155
+ return v
156
+
157
+ @field_validator("TAG_POSITION_MOVIE", "TAG_POSITION_SERIE", mode="before")
158
+ @classmethod
159
+ def parse_tag_position(cls, v):
160
+ if isinstance(v, str):
161
+ return [x.strip() for x in v.split(",") if x.strip()]
162
+ return v
163
+
164
+
165
+ # /// APP SETTINGS
166
+ class Settings(BaseSettings):
167
+ """
168
+ Set default settings
169
+ """
170
+ unit3DwebUp: Unit3DwebUp = Field(default_factory=Unit3DwebUp)
171
+ tracker: TrackerConfig = Field(default_factory=TrackerConfig)
172
+ torrent: TorrentClientConfig = Field(default_factory=TorrentClientConfig)
173
+ prefs: UserPreferences = Field(default_factory=UserPreferences)
174
+
175
+ model_config = SettingsConfigDict(
176
+ env_nested_delimiter="__",
177
+ # /// lo utilizzo quando lo testo in locale
178
+ # docker utilizza 'env_file:' nel suo file yml
179
+ env_file=".env" if not os.getenv("DOCKER") else None,
180
+ extra="ignore"
181
+ )
182
+
183
+
184
+ @lru_cache
185
+ def get_settings() -> Settings:
186
+ """
187
+ :return: settings cached
188
+ """
189
+ logger = get_logger("settings_logger")
190
+
191
+ try:
192
+ settings = Settings()
193
+ except ValidationError as e:
194
+ for err in e.errors():
195
+ field_path = ".".join(str(loc) for loc in err["loc"])
196
+ logger.warning(f"{field_path} value not set or invalid")
197
+ logger.warning("-" * 50)
198
+
199
+ raise SystemExit(1)
200
+
201
+ # Create a folder for each tracker name in the MULTI_TRACKER environment variable
202
+ torrent_archive_path = Path("/home/app/torrent_archive") if os.getenv("DOCKER") == "true" else Path(
203
+ settings.prefs.TORRENT_ARCHIVE_PATH)
204
+ if not Path.exists(torrent_archive_path):
205
+ logger.warning(f"The path {torrent_archive_path} does not exist")
206
+ raise SystemExit(1)
207
+
208
+ for tracker_name in settings.tracker.MULTI_TRACKER:
209
+ torrent_archive_tracker_path = Path(torrent_archive_path) / tracker_name.upper()
210
+ os.makedirs(torrent_archive_tracker_path, exist_ok=True)
211
+
212
+ return settings
config/sis.py ADDED
@@ -0,0 +1,137 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # List of constants pointing to the sis tracker
4
+ # TODO: Add automode to extract these constants?
5
+ sis_data = {
6
+ "CATEGORY": {"movie": 1,
7
+ "series": 2,
8
+ "ebook": 15,
9
+ "edicola": 17,
10
+ "xxx": 19,
11
+ "Music": 3,
12
+ "game": 7,
13
+ "software": 23,
14
+ "eventi sportivi": 24,
15
+ "misc": 25},
16
+
17
+ "FREELECH": {"size20": 100,
18
+ "size15": 75,
19
+ "size10": 50,
20
+ "size5": 25},
21
+
22
+ "TYPE_ID": {
23
+ "encode": 15,
24
+ "web": 27,
25
+ "web-dl": 27,
26
+ "webrip": 27,
27
+ "remux": 7,
28
+ "disk": 26,
29
+ "cinemanews": 42,
30
+ "hdtv": 33,
31
+ "windows": 31,
32
+ "pc": 31,
33
+ "linux": 39,
34
+ "android": 38,
35
+ "appleos": 32,
36
+ "mp3": 25,
37
+ "flac": 24,
38
+ "epub": 48,
39
+ "pdf": 49,
40
+ "altro": 47,
41
+
42
+ },
43
+ "TYPE_ID_AUDIO": {
44
+ "flac": 24,
45
+ "alac": 8,
46
+ "ac3": 9,
47
+ "aac": 10,
48
+ "mp3": 25,
49
+ },
50
+ "TAGS": {
51
+ "SD": 1,
52
+ "HD": 0,
53
+ },
54
+ "RESOLUTION": {
55
+ "4320p": 1,
56
+ "2160p": 2,
57
+ '1440p': 3,
58
+ "1080p": 3,
59
+ "1080i": 4,
60
+ "720p": 5,
61
+ "576p": 6,
62
+ "576i": 7,
63
+ "480p": 8,
64
+ "480i": 9,
65
+ "altro": 11,
66
+ },
67
+ "CODEC": [
68
+ "h261",
69
+ "h262",
70
+ "h263",
71
+ "h264",
72
+ "x264",
73
+ "x265",
74
+ "avc",
75
+ "h265",
76
+ "hevc",
77
+ "vp8",
78
+ "vp9",
79
+ "av1",
80
+ "mpeg-1",
81
+ "mpeg-4",
82
+ "wmv",
83
+ "theora",
84
+ "divx",
85
+ "xvid",
86
+ "prores",
87
+ "dnxhd",
88
+ "cinepak",
89
+ "indeo",
90
+ "dv",
91
+ "ffv1",
92
+ "sorenson",
93
+ "rv40",
94
+ "cineform",
95
+ "huffyuv",
96
+ "mjpeg",
97
+ "lagarith",
98
+ "msu",
99
+ "rle",
100
+ "dirac",
101
+ "wmv3",
102
+ "vorbis",
103
+ "smpte",
104
+ "mjpeg",
105
+ "ffvhuff",
106
+ "v210",
107
+ "yuv4:2:2",
108
+ "yuv4:4:4",
109
+ "hap",
110
+ "sheervideo",
111
+ "ut",
112
+ "quicktime",
113
+ "rududu",
114
+ "h.266",
115
+ "vvc",
116
+ "mjpeg 4:2:0",
117
+ "h.263+",
118
+ "h.263++",
119
+ "vp4",
120
+ "vp5",
121
+ "vp6",
122
+ "vp7",
123
+ "vp8",
124
+ "vp9",
125
+ "vp10",
126
+ "vp11",
127
+ "vp12",
128
+ "vp3",
129
+ "vp2",
130
+ "vp1",
131
+ "amv",
132
+ "daala",
133
+ "gecko",
134
+ "nvenc",
135
+ "bluray",
136
+ ],
137
+ }