Skip to content

Commit 32bd2ba

Browse files
committed
feat: get mediainfo mini
1 parent 3c6aceb commit 32bd2ba

File tree

11 files changed

+216
-82
lines changed

11 files changed

+216
-82
lines changed

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ make run
2828

2929
or you can use docker to run the project, see [docker-compose.yml](./deploy/docker-compose.yml) for more details.
3030

31+
### CLI
32+
33+
```
34+
35+
```
36+
3137
### Configuration
3238

3339
#### Server Config:

animepipeline/cli/__init__.py

Whitespace-only changes.

animepipeline/cli/btf/__init__.py

Whitespace-only changes.

animepipeline/cli/rename/__init__.py

Whitespace-only changes.

animepipeline/loop.py

+8-11
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from animepipeline.bt import QBittorrentManager
99
from animepipeline.config import NyaaConfig, RSSConfig, ServerConfig
1010
from animepipeline.encode import FinalRipClient
11-
from animepipeline.mediainfo import FileNameInfo, gen_file_name
11+
from animepipeline.mediainfo import FileNameInfo, rename_file
1212
from animepipeline.pool import AsyncTaskExecutor
1313
from animepipeline.post import TGChannelSender
1414
from animepipeline.rss import TorrentInfo, parse_nyaa
@@ -218,26 +218,23 @@ async def pipeline_finalrip(self, task_info: TaskInfo) -> None:
218218

219219
# rename temp file
220220
try:
221-
gen_name = gen_file_name(
221+
finalrip_downloaded_path = rename_file(
222222
FileNameInfo(
223-
path=temp_saved_path, episode=task_info.episode, name=task_info.name, uploader=task_info.uploader
223+
path=temp_saved_path,
224+
episode=task_info.episode,
225+
name=task_info.name,
226+
uploader=task_info.uploader,
227+
type="WEBRip",
224228
)
225229
)
226-
finalrip_downloaded_path = Path(task_info.download_path) / gen_name
227230
except Exception as e:
228231
logger.error(f"Failed to generate file name: {e}")
229232
raise e
230233

231-
if finalrip_downloaded_path.exists():
232-
finalrip_downloaded_path.unlink()
233-
logger.warning(f"Encode File already exists, remove it: {finalrip_downloaded_path}")
234-
235-
temp_saved_path.rename(finalrip_downloaded_path)
236-
237234
logger.info(f'FinalRip Encode Done for "{finalrip_downloaded_path.name}"')
238235

239236
# update task status
240-
task_status.finalrip_downloaded_path = gen_name
237+
task_status.finalrip_downloaded_path = finalrip_downloaded_path.name
241238
await self.json_store.update_task(task_info.hash, task_status)
242239

243240
async def pipeline_post(self, task_info: TaskInfo) -> None:

animepipeline/mediainfo/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from animepipeline.mediainfo.gen_file_name import gen_file_name, FileNameInfo # noqa
1+
from animepipeline.mediainfo.mediainfomini import gen_file_name, FileNameInfo, rename_file, get_media_info # noqa

animepipeline/mediainfo/gen_file_name.py

-68
This file was deleted.
+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import json
2+
from datetime import datetime
3+
from pathlib import Path
4+
from typing import List, Tuple, Union
5+
6+
import pymediainfo
7+
from loguru import logger
8+
9+
from animepipeline.mediainfo.type import FileNameInfo, MediaInfo
10+
11+
12+
def get_media_info(video_path: Union[str, Path]) -> MediaInfo:
13+
"""
14+
Get the mini media info of the video file
15+
16+
:param video_path:
17+
"""
18+
logger.info(f"Get media info of {video_path}...")
19+
20+
video_path = Path(video_path)
21+
22+
encode_media_info = pymediainfo.MediaInfo.parse(video_path, output="JSON")
23+
encode_tracks = json.loads(encode_media_info)["media"]["track"]
24+
25+
release_name = video_path.name
26+
release_date = datetime.now()
27+
# date_YMd = release_date.strftime("%Y:%M:%d")
28+
29+
try:
30+
release_size = encode_tracks[0]["FileSize_String"]
31+
except Exception:
32+
logger.warning(f'Failed to get "FileSize_String" of {video_path}')
33+
release_size = encode_tracks[0]["FileSize"]
34+
release_size = round(int(release_size) / (1024 * 1024), 2)
35+
if release_size > 1000:
36+
release_size = round(release_size / 1024, 2)
37+
release_size = str(release_size) + " GiB"
38+
else:
39+
release_size = str(release_size) + " MiB"
40+
41+
try:
42+
release_format = encode_tracks[0]["Format"]
43+
except Exception as e:
44+
logger.warning(f'Failed to get "Format" of {video_path}, set to "Unknown", {e}')
45+
release_format = "Unknown"
46+
47+
try:
48+
overall_bitrate = encode_tracks[0]["OverallBitRate_String"]
49+
except Exception:
50+
logger.warning(f'Failed to get "OverallBitRate_String" of {video_path}')
51+
try:
52+
overall_bitrate = encode_tracks[0]["OverallBitRate"]
53+
overall_bitrate = round(int(overall_bitrate) / 1000, 2)
54+
if overall_bitrate > 10000:
55+
overall_bitrate = round(overall_bitrate / 1000, 2)
56+
if overall_bitrate > 1000:
57+
overall_bitrate = round(overall_bitrate / 1000, 2)
58+
overall_bitrate = str(overall_bitrate) + " Gb/s"
59+
else:
60+
overall_bitrate = str(overall_bitrate) + " Mb/s"
61+
else:
62+
overall_bitrate = str(overall_bitrate) + " kb/s"
63+
except Exception as e:
64+
logger.warning(f'Failed to get "OverallBitRate" of {video_path}, set to "Unknown", {e}')
65+
overall_bitrate = "Unknown"
66+
67+
# VIDEO TRACK
68+
resolution = (0, 0)
69+
bit_depth = 0
70+
frame_rate = 0.0
71+
video_format = "Unknown"
72+
format_profile = "Unknown"
73+
74+
video_track_id = 0
75+
try:
76+
for _, video_track in enumerate(encode_tracks):
77+
if video_track["@type"] == "Video":
78+
resolution = (int(video_track["Width"]), int(video_track["Height"]))
79+
bit_depth = int(video_track["BitDepth"])
80+
frame_rate = float(video_track["FrameRate"])
81+
video_format = video_track["Format"]
82+
format_profile = video_track["Format_Profile"]
83+
video_track_id += 1
84+
except Exception as e:
85+
logger.warning(f"Exceptional video track: {video_track_id} of {video_path}, {e}")
86+
87+
if video_track_id != 1:
88+
logger.warning(f"There may be multiple video tracks or no video tracks, please check {video_path}")
89+
90+
# AUDIO TRACK
91+
audios: List[Tuple[str, int, str]] = []
92+
93+
audio_track_id = 1
94+
try:
95+
for _, audio_track in enumerate(encode_tracks):
96+
if audio_track["@type"] == "Audio":
97+
language = audio_track.get("Language_String", audio_track.get("Language", "Ambiguous!!!"))
98+
audios.append((language, int(audio_track["Channels"]), audio_track["Format"]))
99+
audio_track_id += 1
100+
except Exception as e:
101+
logger.warning(f"Exceptional audio track: {audio_track_id} of {video_path}, {e}")
102+
103+
# SUBTITLE TRACK
104+
subtitles: List[Tuple[str, str]] = []
105+
106+
subtitle_track_id = 1
107+
try:
108+
for _, subtitle_track in enumerate(encode_tracks):
109+
if subtitle_track["@type"] == "Text":
110+
language = subtitle_track.get("Language_String", subtitle_track.get("Language", "Ambiguous!!!"))
111+
subtitles.append((language, subtitle_track["Format"]))
112+
subtitle_track_id += 1
113+
except Exception as e:
114+
logger.warning(f"Exceptional subtitle track: {subtitle_track_id} of {video_path}, {e}")
115+
116+
return MediaInfo(
117+
release_name=release_name,
118+
release_date=release_date,
119+
release_size=release_size,
120+
release_format=release_format,
121+
overall_bitrate=overall_bitrate,
122+
resolution=resolution,
123+
bit_depth=bit_depth,
124+
frame_rate=frame_rate,
125+
format=video_format,
126+
format_profile=format_profile,
127+
audios=audios,
128+
subtitles=subtitles,
129+
)
130+
131+
132+
def gen_file_name(anime_info: FileNameInfo) -> str:
133+
"""
134+
Auto generate the file name, based on the media info of the file
135+
136+
anime_info: FileNameInfo (path: xx.mkv, episode: 1, name: Fate/Kaleid Liner Prisma Illya, uploader: TensoRaws, type: WEBRip)
137+
138+
-> [TensoRaws] Fate/Kaleid Liner Prisma Illya [01] [WEBRip 1080p HEVC-10bit FLAC].mkv
139+
140+
:param anime_info: FileNameInfo
141+
:return:
142+
"""
143+
media_info = get_media_info(anime_info.path)
144+
resolution_heigh = str(media_info.resolution[1]) + "p"
145+
bit_depth = str(media_info.bit_depth) + "bit"
146+
147+
video_format = media_info.format
148+
149+
audio_format_list = [audio[2] for audio in media_info.audios]
150+
audio_format = "FLAC" if "FLAC" in audio_format_list else audio_format_list[0]
151+
152+
file_format = Path(anime_info.path).suffix
153+
154+
return f"[{anime_info.uploader}] {anime_info.name} [{str(anime_info.episode).zfill(2)}] [{anime_info.type} {resolution_heigh} {video_format}-{bit_depth} {audio_format}]{file_format}"
155+
156+
157+
def rename_file(anime_info: FileNameInfo) -> Path:
158+
"""
159+
Rename the file name, based on the media info of the file
160+
161+
:param anime_info: FileNameInfo
162+
:return:
163+
"""
164+
anime_path = Path(anime_info.path)
165+
166+
gen_name = gen_file_name(anime_info)
167+
gen_path = anime_path.parent / gen_name
168+
169+
if gen_path.exists():
170+
gen_path.unlink()
171+
logger.warning(f"Encode File already exists, remove it: {gen_path}")
172+
173+
anime_path.rename(gen_path)
174+
175+
return gen_path

animepipeline/mediainfo/type.py

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from datetime import datetime
2+
from typing import List, Tuple
3+
14
from pydantic import BaseModel, FilePath
25

36

@@ -6,3 +9,19 @@ class FileNameInfo(BaseModel):
69
episode: int
710
name: str
811
uploader: str
12+
type: str = "WEBRip"
13+
14+
15+
class MediaInfo(BaseModel):
16+
release_name: str
17+
release_date: datetime
18+
release_size: str # 1.35 GiB
19+
release_format: str # Matroska
20+
overall_bitrate: str # 1919.8 Mb/s
21+
resolution: Tuple[int, int] # (1920, 1080)
22+
bit_depth: int # 10
23+
frame_rate: float # 23.976
24+
format: str # HEVC
25+
format_profile: str # Main@L5@Main
26+
audios: List[Tuple[str, int, str]] # Chinese, 2 channels, FLAC
27+
subtitles: List[Tuple[str, str]] # CHS, PGS

animepipeline/template/__init__.py

Whitespace-only changes.

tests/test_mediainfo.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
from animepipeline.mediainfo.gen_file_name import gen_file_name
1+
from animepipeline.mediainfo import gen_file_name, get_media_info
22
from animepipeline.mediainfo.type import FileNameInfo
33

44
from .util import TEST_VIDEO_PATH
55

66

7+
def test_get_media_info() -> None:
8+
media_info = get_media_info(video_path=TEST_VIDEO_PATH)
9+
print(media_info)
10+
11+
712
def test_gen_file_name() -> None:
813
anime_info = FileNameInfo(
914
path=str(TEST_VIDEO_PATH),
@@ -13,4 +18,4 @@ def test_gen_file_name() -> None:
1318
)
1419

1520
name = gen_file_name(anime_info=anime_info)
16-
assert name == "[TensoRaws] test 114 [01] [144p AVC-8bit AAC].mp4"
21+
assert name == "[TensoRaws] test 114 [01] [WEBRip 144p AVC-8bit AAC].mp4"

0 commit comments

Comments
 (0)