|
11 | 11 | from app.utils.string import StringUtils |
12 | 12 | from app.utils.tokens import Tokens |
13 | 13 | from app.core.meta.streamingplatform import StreamingPlatforms |
| 14 | +from app.utils import rust_accel |
14 | 15 |
|
15 | 16 |
|
16 | 17 | class MetaVideo(MetaBase): |
@@ -102,59 +103,61 @@ def __init__(self, title: str, subtitle: str = None, isfile: bool = False): |
102 | 103 | title = re.sub(r'[0-9.]+\s*[MGT]i?B(?![A-Z]+)', "", title, flags=re.IGNORECASE) |
103 | 104 | # 把年月日去掉 |
104 | 105 | title = re.sub(r'\d{4}[\s._-]\d{1,2}[\s._-]\d{1,2}', "", title) |
105 | | - # 拆分tokens |
106 | | - tokens = Tokens(title) |
107 | | - # 实例化StreamingPlatforms对象 |
108 | | - streaming_platforms = StreamingPlatforms() |
109 | 106 | media_exts = settings.RMT_MEDIAEXT + settings.RMT_SUBEXT + settings.RMT_AUDIOEXT |
110 | | - # 解析名称、年份、季、集、资源类型、分辨率等 |
111 | | - token = tokens.get_next() |
112 | | - while token: |
113 | | - self._index += 1 # 更新当前处理的token索引 |
114 | | - # Part |
115 | | - self.__init_part(token, tokens) |
116 | | - # 标题 |
117 | | - if self._continue_flag: |
118 | | - self.__init_name(token, media_exts) |
119 | | - # 年份 |
120 | | - if self._continue_flag: |
121 | | - self.__init_year(token) |
122 | | - # 分辨率 |
123 | | - if self._continue_flag: |
124 | | - self.__init_resource_pix(token) |
125 | | - # 季 |
126 | | - if self._continue_flag: |
127 | | - self.__init_season(token) |
128 | | - # 集 |
129 | | - if self._continue_flag: |
130 | | - self.__init_episode(token) |
131 | | - # 资源类型 |
132 | | - if self._continue_flag: |
133 | | - self.__init_resource_type(token) |
134 | | - # 流媒体平台 |
135 | | - if self._continue_flag: |
136 | | - self.__init_web_source(token, tokens, streaming_platforms) |
137 | | - # 视频编码 |
138 | | - if self._continue_flag: |
139 | | - self.__init_video_encode(token) |
140 | | - # 视频位深 |
141 | | - if self._continue_flag: |
142 | | - self.__init_video_bit(token) |
143 | | - # 音频编码 |
144 | | - if self._continue_flag: |
145 | | - self.__init_audio_encode(token) |
146 | | - # 帧率 |
147 | | - if self._continue_flag: |
148 | | - self.__init_fps(token) |
149 | | - # 取下一个,直到没有为卡 |
| 107 | + rust_parse = rust_accel.parse_video_title(title, isfile=isfile, media_exts=media_exts) |
| 108 | + if not self.__apply_rust_parse(rust_parse): |
| 109 | + # 拆分tokens |
| 110 | + tokens = Tokens(title) |
| 111 | + # 实例化StreamingPlatforms对象 |
| 112 | + streaming_platforms = StreamingPlatforms() |
| 113 | + # 解析名称、年份、季、集、资源类型、分辨率等 |
150 | 114 | token = tokens.get_next() |
151 | | - self._continue_flag = True |
152 | | - # 合成质量 |
153 | | - if self._effect: |
154 | | - self._effect.reverse() |
155 | | - self.resource_effect = " ".join(self._effect) |
156 | | - if self._source: |
157 | | - self.resource_type = self._source.strip() |
| 115 | + while token: |
| 116 | + self._index += 1 # 更新当前处理的token索引 |
| 117 | + # Part |
| 118 | + self.__init_part(token, tokens) |
| 119 | + # 标题 |
| 120 | + if self._continue_flag: |
| 121 | + self.__init_name(token, media_exts) |
| 122 | + # 年份 |
| 123 | + if self._continue_flag: |
| 124 | + self.__init_year(token) |
| 125 | + # 分辨率 |
| 126 | + if self._continue_flag: |
| 127 | + self.__init_resource_pix(token) |
| 128 | + # 季 |
| 129 | + if self._continue_flag: |
| 130 | + self.__init_season(token) |
| 131 | + # 集 |
| 132 | + if self._continue_flag: |
| 133 | + self.__init_episode(token) |
| 134 | + # 资源类型 |
| 135 | + if self._continue_flag: |
| 136 | + self.__init_resource_type(token) |
| 137 | + # 流媒体平台 |
| 138 | + if self._continue_flag: |
| 139 | + self.__init_web_source(token, tokens, streaming_platforms) |
| 140 | + # 视频编码 |
| 141 | + if self._continue_flag: |
| 142 | + self.__init_video_encode(token) |
| 143 | + # 视频位深 |
| 144 | + if self._continue_flag: |
| 145 | + self.__init_video_bit(token) |
| 146 | + # 音频编码 |
| 147 | + if self._continue_flag: |
| 148 | + self.__init_audio_encode(token) |
| 149 | + # 帧率 |
| 150 | + if self._continue_flag: |
| 151 | + self.__init_fps(token) |
| 152 | + # 取下一个,直到没有为卡 |
| 153 | + token = tokens.get_next() |
| 154 | + self._continue_flag = True |
| 155 | + # 合成质量 |
| 156 | + if self._effect: |
| 157 | + self._effect.reverse() |
| 158 | + self.resource_effect = " ".join(self._effect) |
| 159 | + if self._source: |
| 160 | + self.resource_type = self._source.strip() |
158 | 161 | # 提取原盘DIY |
159 | 162 | if self.resource_type and "BluRay" in self.resource_type: |
160 | 163 | if (self.subtitle and re.findall(r'D[Ii]Y', self.subtitle)) \ |
@@ -185,6 +188,62 @@ def __init__(self, title: str, subtitle: str = None, isfile: bool = False): |
185 | 188 | if not self.video_bit: |
186 | 189 | self.video_bit = self.extract_video_bit(self.video_encode) |
187 | 190 |
|
| 191 | + def __apply_rust_parse(self, rust_parse: Optional[dict]) -> bool: |
| 192 | + """ |
| 193 | + 应用 Rust 主识别结果;成功时跳过 Python token 主循环。 |
| 194 | + """ |
| 195 | + if not rust_parse or not rust_parse.get("complete"): |
| 196 | + return False |
| 197 | + self.cn_name = rust_parse.get("cn_name") |
| 198 | + self.en_name = rust_parse.get("en_name") |
| 199 | + if rust_parse.get("year"): |
| 200 | + self.year = str(rust_parse.get("year")) |
| 201 | + self.part = rust_parse.get("part") |
| 202 | + self.__merge_rust_parse(rust_parse) |
| 203 | + media_type = rust_parse.get("type") |
| 204 | + if media_type == "tv": |
| 205 | + self.type = MediaType.TV |
| 206 | + elif media_type == "movie": |
| 207 | + self.type = MediaType.MOVIE |
| 208 | + return True |
| 209 | + |
| 210 | + def __merge_rust_parse(self, rust_parse: Optional[dict]) -> None: |
| 211 | + """ |
| 212 | + 合并 Rust 预解析结果,仅补齐 Python 识别未命中的资源字段。 |
| 213 | + """ |
| 214 | + if not rust_parse: |
| 215 | + return |
| 216 | + if not self.year and rust_parse.get("year"): |
| 217 | + self.year = str(rust_parse.get("year")) |
| 218 | + if self.begin_season is None and rust_parse.get("begin_season") is not None: |
| 219 | + self.begin_season = int(rust_parse.get("begin_season")) |
| 220 | + self.type = MediaType.TV |
| 221 | + if self.end_season is None and rust_parse.get("end_season") is not None: |
| 222 | + self.end_season = int(rust_parse.get("end_season")) |
| 223 | + if not self.total_season and rust_parse.get("total_season"): |
| 224 | + self.total_season = int(rust_parse.get("total_season")) |
| 225 | + if self.begin_episode is None and rust_parse.get("begin_episode") is not None: |
| 226 | + self.begin_episode = int(rust_parse.get("begin_episode")) |
| 227 | + self.type = MediaType.TV |
| 228 | + if self.end_episode is None and rust_parse.get("end_episode") is not None: |
| 229 | + self.end_episode = int(rust_parse.get("end_episode")) |
| 230 | + if not self.total_episode and rust_parse.get("total_episode"): |
| 231 | + self.total_episode = int(rust_parse.get("total_episode")) |
| 232 | + if not self.resource_pix and rust_parse.get("resource_pix"): |
| 233 | + self.resource_pix = rust_parse.get("resource_pix") |
| 234 | + if not self.resource_type and rust_parse.get("resource_type"): |
| 235 | + self.resource_type = rust_parse.get("resource_type") |
| 236 | + if not self.resource_effect and rust_parse.get("resource_effect"): |
| 237 | + self.resource_effect = rust_parse.get("resource_effect") |
| 238 | + if not self.video_encode and rust_parse.get("video_encode"): |
| 239 | + self.video_encode = rust_parse.get("video_encode") |
| 240 | + if not self.video_bit and rust_parse.get("video_bit"): |
| 241 | + self.video_bit = rust_parse.get("video_bit") |
| 242 | + if not self.audio_encode and rust_parse.get("audio_encode"): |
| 243 | + self.audio_encode = rust_parse.get("audio_encode") |
| 244 | + if self.fps is None and rust_parse.get("fps") is not None: |
| 245 | + self.fps = int(rust_parse.get("fps")) |
| 246 | + |
188 | 247 | @staticmethod |
189 | 248 | def __get_title_from_description(description: str) -> Optional[str]: |
190 | 249 | """ |
|
0 commit comments