Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53a8469b8f | ||
|
|
4abc40e75d | ||
|
|
f165316c02 | ||
|
|
51322aa86e | ||
|
|
3842cb4ae2 | ||
|
|
b9bb0c7e2f |
@@ -13,6 +13,7 @@ This is a command-line application that analyzes video files using `ffprobe` to
|
|||||||
4. **OMDb API Lookup (Optional):** If an IMDB ID is provided, the application queries the OMDb API to retrieve movie title and release date.
|
4. **OMDb API Lookup (Optional):** If an IMDB ID is provided, the application queries the OMDb API to retrieve movie title and release date.
|
||||||
|
|
||||||
5. **Output:** Finally, it prints a command string based on the extracted information. This command string is likely intended for further video processing or encoding.
|
5. **Output:** Finally, it prints a command string based on the extracted information. This command string is likely intended for further video processing or encoding.
|
||||||
|
- Every audio stream that is side loaded, must be converted to 5.1 channel layout with `channelmap=channel_layout=5.1`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -6,11 +6,15 @@ from pathlib import Path
|
|||||||
|
|
||||||
from models.streams import VideoFile, VideoStream, AudioStream, SubtitleStream
|
from models.streams import VideoFile, VideoStream, AudioStream, SubtitleStream
|
||||||
from movie_details import get_movie_details
|
from movie_details import get_movie_details
|
||||||
|
from lib.fs import write_shell_script
|
||||||
|
|
||||||
|
|
||||||
def parse_streams(stream_data: dict, VideoFile: VideoFile) -> VideoFile:
|
def parse_streams(stream_data: dict, VideoFile: VideoFile) -> VideoFile:
|
||||||
for stream in stream_data["streams"]:
|
for stream in stream_data["streams"]:
|
||||||
if stream["codec_type"] == "video":
|
if (
|
||||||
|
stream["codec_type"] == "video"
|
||||||
|
and stream["disposition"]["attached_pic"] == 0
|
||||||
|
):
|
||||||
VideoFile.video_streams.append(VideoStream(**stream))
|
VideoFile.video_streams.append(VideoStream(**stream))
|
||||||
elif stream["codec_type"] == "audio":
|
elif stream["codec_type"] == "audio":
|
||||||
VideoFile.audio_streams.append(AudioStream(**stream))
|
VideoFile.audio_streams.append(AudioStream(**stream))
|
||||||
@@ -42,6 +46,10 @@ def main(filename: Path, imdb: str, nosubtitles: bool):
|
|||||||
]
|
]
|
||||||
result = subprocess.run(cmd, capture_output=True, check=True)
|
result = subprocess.run(cmd, capture_output=True, check=True)
|
||||||
data = parse_streams(json.loads(result.stdout), video_details)
|
data = parse_streams(json.loads(result.stdout), video_details)
|
||||||
|
export_data = " ".join(data.cmd())
|
||||||
|
export_path = Path(filename).parent / "encode.sh"
|
||||||
|
write_shell_script(export_data, export_path)
|
||||||
|
print(Path(filename).parent)
|
||||||
print(" ".join(data.cmd()))
|
print(" ".join(data.cmd()))
|
||||||
# json.dump(data, sys.stdout, indent=4)
|
# json.dump(data, sys.stdout, indent=4)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from os import chmod
|
||||||
|
|
||||||
|
|
||||||
def sanitize_filename(filename: str) -> str:
|
def sanitize_filename(filename: str) -> str:
|
||||||
characters_not_allowed = ["<", ">", ":", '"', "/", "\\", "|", "?", "*", " ", "'"]
|
characters_not_allowed = ["<", ">", ":", '"', "/", "\\", "|", "?", "*", " ", "'"]
|
||||||
for char in characters_not_allowed:
|
for char in characters_not_allowed:
|
||||||
filename = filename.replace(char, "")
|
filename = filename.replace(char, "")
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
def write_shell_script(script: str, filename: Path):
|
||||||
|
if filename.exists():
|
||||||
|
raise FileExistsError("encode.sh already exists")
|
||||||
|
with open(filename, "w") as f:
|
||||||
|
f.write("#!/bin/bash\n")
|
||||||
|
f.write(script)
|
||||||
|
|
||||||
|
chmod(filename, 0o755)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from pydantic import BaseModel, Field
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from functools import cached_property
|
||||||
|
|
||||||
from lib.fs import sanitize_filename
|
from lib.fs import sanitize_filename
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ class VideoStream(BaseModel):
|
|||||||
disposition: Disposition
|
disposition: Disposition
|
||||||
tags: Tags
|
tags: Tags
|
||||||
|
|
||||||
@property
|
@cached_property
|
||||||
def fps(self) -> float:
|
def fps(self) -> float:
|
||||||
frame_numbers = [int(x) for x in self.avg_frame_rate.split("/")]
|
frame_numbers = [int(x) for x in self.avg_frame_rate.split("/")]
|
||||||
return frame_numbers[0] / frame_numbers[1]
|
return frame_numbers[0] / frame_numbers[1]
|
||||||
@@ -106,7 +107,7 @@ class VideoFile(BaseModel):
|
|||||||
"-loglevel",
|
"-loglevel",
|
||||||
"error",
|
"error",
|
||||||
"-i",
|
"-i",
|
||||||
str(self.video_path.absolute()),
|
f"'{str(self.video_path.absolute())}'",
|
||||||
"-map_metadata",
|
"-map_metadata",
|
||||||
"-1",
|
"-1",
|
||||||
"-metadata",
|
"-metadata",
|
||||||
|
|||||||
Reference in New Issue
Block a user