Skip to content

Commit

Permalink
fix: add support for .m4v files (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
natelandau committed Mar 23, 2024
1 parent c7569a0 commit 694d20e
Show file tree
Hide file tree
Showing 12 changed files with 452 additions and 347 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ default_stages: [commit, manual]
fail_fast: true
repos:
- repo: "https://github.com/commitizen-tools/commitizen"
rev: v3.18.3
rev: v3.20.0
hooks:
- id: commitizen
- id: commitizen-branch
Expand Down Expand Up @@ -59,7 +59,7 @@ repos:
entry: yamllint --strict --config-file .yamllint.yml

- repo: "https://github.com/charliermarsh/ruff-pre-commit"
rev: "v0.3.2"
rev: "v0.3.4"
hooks:
- id: ruff
args: ["--extend-ignore", "I001,D401"]
Expand Down
229 changes: 129 additions & 100 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
ruff = "^0.3.2"
types-requests = "^2.31.0.20240311"
typos = "^1.19.0"
yamllint = "^1.35.1"

[tool.commitizen]
bump_message = "bump(release): v$current_version → v$new_version"
Expand Down
38 changes: 31 additions & 7 deletions src/vid_cleaner/cli/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,40 @@ def clean(
dry_run: bool,
verbosity: int,
) -> None:
"""Clean command."""
"""Processes a list of video files with various cleaning and conversion options.
This function performs a series of operations on video files, including reordering streams, processing audio and subtitle streams according to specified preferences, and converting the video to specified formats and resolutions. It can optionally perform these operations as a dry run, which does not apply any changes. If not a dry run, it handles output files according to specified replacement and verbosity settings.
Args:
files: A list of VideoFile objects to process.
out: A Path object representing the output directory for processed files.
replace: If True, replace the original files with the processed ones.
downmix_stereo: If True, downmix audio to stereo.
drop_original_audio: If True, drop the original audio streams from the file.
keep_all_subtitles: If True, keep all subtitle streams.
keep_commentary: If True, keep commentary audio streams.
keep_local_subtitles: If True, keep subtitle streams in the local language.
subs_drop_local: If True, drop local language subtitle streams.
langs: A comma-separated string of language codes to keep in the processed video. None keeps default languages.
h265: If True, convert video to H.265 codec.
vp9: If True, convert video to VP9 codec.
video_1080: If True, convert video to 1080p resolution.
force: If True, force conversion even if it might result in loss of quality.
dry_run: If True, perform a trial run without making any changes.
verbosity: An integer that sets the verbosity level of the operation's output.
Raises:
typer.BadParameter: If both h265 and vp9 flags are set to True.
"""
if h265 and vp9:
msg = "Cannot convert to both H265 and VP9"
raise typer.BadParameter(msg)

languages = langs or ",".join(VidCleanerConfig().keep_languages)

for video in files:
logger.info(f"⇨ {video.path.name}")

if h265 and vp9:
msg = "Cannot convert to both H265 and VP9"
raise typer.BadParameter(msg)

video.reorder_streams(dry_run=dry_run)

video.process_streams(
Expand All @@ -56,10 +80,10 @@ def clean(
video.video_to_1080p(force=force, dry_run=dry_run)

if h265:
video._convert_to_h265(force=force, dry_run=dry_run)
video.convert_to_h265(force=force, dry_run=dry_run)

if vp9:
video._convert_to_vp9(force=force, dry_run=dry_run)
video.convert_to_vp9(force=force, dry_run=dry_run)

if not dry_run:
out_file = tmp_to_output(
Expand Down
6 changes: 4 additions & 2 deletions src/vid_cleaner/cli/clip.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
def clip(
files: list[VideoFile], start: str, duration: str, out: Path, overwrite: bool, dry_run: bool
) -> None:
"""Clips video files based on the specified start time and duration.
"""Clips video files based on the specified start time and duration, saving the output in a given directory.
This function processes each video in the provided list, clipping it according to the specified start time and duration. The resulting clips are saved in the specified output directory. The function supports overwriting existing files and performing a dry run, where no actual clipping occurs.
Args:
files: A list of VideoFile objects to be clipped.
Expand All @@ -24,7 +26,7 @@ def clip(
dry_run: A boolean indicating if the clip operation should be simulated (no actual clipping).
Raises:
typer.BadParameter: If either 'start' or 'duration' does not match the expected time format.
typer.BadParameter: If either 'start' or 'duration' does not match the expected HH:MM:SS time format.
"""
time_pattern = re.compile(r"^\d{2}:\d{2}:\d{2}$")

Expand Down
12 changes: 11 additions & 1 deletion src/vid_cleaner/cli/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@


def inspect(files: list[VideoFile], json_output: bool = False) -> None:
"""Inspect command."""
"""Inspect a list of video files and output their metadata details.
Iterates over a list of video files, using `ffprobe` to inspect each file. Depending on the `json_output` flag, the function either prints a JSON representation of the video file details or a formatted table of the video streams. The function exits the program after printing the details of all video files.
Args:
files: A list of `VideoFile` objects to inspect.
json_output: A boolean flag. If True, output the details in JSON format. Defaults to False.
Raises:
typer.Exit: Exits the program after printing the details of all video files.
"""
for video in files:
if json_output:
console.print(video.ffprobe_json())
Expand Down
5 changes: 1 addition & 4 deletions src/vid_cleaner/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@

def pass_opt_without_value(value: str) -> bool:
"""Confz does not work well with Typer options. Confz requires a value for each CLI option, but Typer does not. To workaround this, for example, if --log-to-file is passed, we set the value to "True" regardless of what follows the CLI option."""
if value:
return True

return False
return bool(value)


OPT_BOOLEAN = Annotated[
Expand Down
12 changes: 12 additions & 0 deletions src/vid_cleaner/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
import typer


class VideoContainerTypes(str, Enum):
"""Video container types for vid-cleaner."""

MKV = ".mkv"
MP4 = ".mp4"
AVI = ".avi"
WEBM = ".webm"
MOV = ".mov"
WMV = ".wmv"
M4V = ".m4v"


class CodecTypes(str, Enum):
"""Codec types for vid-cleaner."""

Expand Down
Loading

0 comments on commit 694d20e

Please sign in to comment.