diff options
| -rw-r--r-- | poetry.lock | 30 | ||||
| -rw-r--r-- | pyproject.toml | 1 | ||||
| -rw-r--r-- | video2story/__main__.py | 40 | ||||
| -rw-r--r-- | video2story/cutter.py | 50 |
4 files changed, 86 insertions, 35 deletions
diff --git a/poetry.lock b/poetry.lock index 4760091..88c60ac 100644 --- a/poetry.lock +++ b/poetry.lock | |||
| @@ -72,34 +72,6 @@ files = [ | |||
| 72 | ] | 72 | ] |
| 73 | 73 | ||
| 74 | [[package]] | 74 | [[package]] |
| 75 | name = "ffmpeg-python" | ||
| 76 | version = "0.2.0" | ||
| 77 | description = "Python bindings for FFmpeg - with complex filtering support" | ||
| 78 | optional = false | ||
| 79 | python-versions = "*" | ||
| 80 | files = [ | ||
| 81 | {file = "ffmpeg-python-0.2.0.tar.gz", hash = "sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127"}, | ||
| 82 | {file = "ffmpeg_python-0.2.0-py3-none-any.whl", hash = "sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"}, | ||
| 83 | ] | ||
| 84 | |||
| 85 | [package.dependencies] | ||
| 86 | future = "*" | ||
| 87 | |||
| 88 | [package.extras] | ||
| 89 | dev = ["Sphinx (==2.1.0)", "future (==0.17.1)", "numpy (==1.16.4)", "pytest (==4.6.1)", "pytest-mock (==1.10.4)", "tox (==3.12.1)"] | ||
| 90 | |||
| 91 | [[package]] | ||
| 92 | name = "future" | ||
| 93 | version = "1.0.0" | ||
| 94 | description = "Clean single-source support for Python 3 and 2" | ||
| 95 | optional = false | ||
| 96 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" | ||
| 97 | files = [ | ||
| 98 | {file = "future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216"}, | ||
| 99 | {file = "future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"}, | ||
| 100 | ] | ||
| 101 | |||
| 102 | [[package]] | ||
| 103 | name = "isort" | 75 | name = "isort" |
| 104 | version = "5.13.2" | 76 | version = "5.13.2" |
| 105 | description = "A Python utility / library to sort Python imports." | 77 | description = "A Python utility / library to sort Python imports." |
| @@ -259,4 +231,4 @@ files = [ | |||
| 259 | [metadata] | 231 | [metadata] |
| 260 | lock-version = "2.0" | 232 | lock-version = "2.0" |
| 261 | python-versions = "^3.10" | 233 | python-versions = "^3.10" |
| 262 | content-hash = "57d800ac4f8df8b2189422300c98cbe5d2c045eaa6f29351e873f8c92bb2ba4d" | 234 | content-hash = "afe0c9ed9e5cb15d216e56fcde897a8e133afb07c69b0a769c68476654684961" |
diff --git a/pyproject.toml b/pyproject.toml index acba697..53270a9 100644 --- a/pyproject.toml +++ b/pyproject.toml | |||
| @@ -7,7 +7,6 @@ readme = "README.md" | |||
| 7 | 7 | ||
| 8 | [tool.poetry.dependencies] | 8 | [tool.poetry.dependencies] |
| 9 | python = "^3.10" | 9 | python = "^3.10" |
| 10 | ffmpeg-python = "^0.2.0" | ||
| 11 | python-telegram = "^0.19.0" | 10 | python-telegram = "^0.19.0" |
| 12 | 11 | ||
| 13 | [tool.poetry.group.dev.dependencies] | 12 | [tool.poetry.group.dev.dependencies] |
diff --git a/video2story/__main__.py b/video2story/__main__.py index 1b65f2a..8e08cac 100644 --- a/video2story/__main__.py +++ b/video2story/__main__.py | |||
| @@ -1,4 +1,7 @@ | |||
| 1 | from argparse import ArgumentParser, RawTextHelpFormatter | 1 | from argparse import ArgumentParser, RawTextHelpFormatter |
| 2 | from os.path import normpath | ||
| 3 | |||
| 4 | from video2story import cut, upload | ||
| 2 | 5 | ||
| 3 | parser = ArgumentParser( | 6 | parser = ArgumentParser( |
| 4 | prog="video2story", | 7 | prog="video2story", |
| @@ -20,10 +23,16 @@ video_parser = subparsers.add_parser( | |||
| 20 | video_parser.add_argument( | 23 | video_parser.add_argument( |
| 21 | "filename", | 24 | "filename", |
| 22 | type=str, | 25 | type=str, |
| 23 | metavar="FILENAME", | 26 | metavar="FILE", |
| 24 | help="Video file name", | 27 | help="Video file name", |
| 25 | ) | 28 | ) |
| 26 | video_parser.add_argument( | 29 | video_parser.add_argument( |
| 30 | "output", | ||
| 31 | type=str, | ||
| 32 | metavar="PATH", | ||
| 33 | help="Output folder for processed videos", | ||
| 34 | ) | ||
| 35 | video_parser.add_argument( | ||
| 27 | "-d", | 36 | "-d", |
| 28 | "--duration", | 37 | "--duration", |
| 29 | type=int, | 38 | type=int, |
| @@ -41,6 +50,23 @@ video_parser.add_argument( | |||
| 41 | action="store_true", | 50 | action="store_true", |
| 42 | help="Remove sound from video.", | 51 | help="Remove sound from video.", |
| 43 | ) | 52 | ) |
| 53 | video_parser.add_argument( | ||
| 54 | "-s", | ||
| 55 | "--start", | ||
| 56 | type=int, | ||
| 57 | metavar="SECONDS", | ||
| 58 | default=None, | ||
| 59 | help="Specifies the second of the video from which processing will begin.", | ||
| 60 | ) | ||
| 61 | video_parser.add_argument( | ||
| 62 | "-e", | ||
| 63 | "--end", | ||
| 64 | type=int, | ||
| 65 | metavar="SECONDS", | ||
| 66 | default=None, | ||
| 67 | help="Specifies the second of the video from which processing will end.", | ||
| 68 | ) | ||
| 69 | |||
| 44 | 70 | ||
| 45 | story_parser = subparsers.add_parser( | 71 | story_parser = subparsers.add_parser( |
| 46 | "story", | 72 | "story", |
| @@ -124,4 +150,14 @@ story_parser.add_argument( | |||
| 124 | 150 | ||
| 125 | 151 | ||
| 126 | args = parser.parse_args() | 152 | args = parser.parse_args() |
| 127 | print(args) | 153 | if args.module == "video": |
| 154 | cut( | ||
| 155 | normpath(args.filename), | ||
| 156 | normpath(args.output), | ||
| 157 | args.duration, | ||
| 158 | args.no_sound, | ||
| 159 | args.start, | ||
| 160 | args.end, | ||
| 161 | ) | ||
| 162 | elif args.module == "story": | ||
| 163 | pass | ||
diff --git a/video2story/cutter.py b/video2story/cutter.py index 880a672..23f035e 100644 --- a/video2story/cutter.py +++ b/video2story/cutter.py | |||
| @@ -1,5 +1,49 @@ | |||
| 1 | import ffmpeg | 1 | from os import makedirs |
| 2 | from os.path import exists, isdir, join | ||
| 3 | from subprocess import Popen | ||
| 2 | 4 | ||
| 3 | 5 | ||
| 4 | def cut(filename: str) -> None: | 6 | def cut( |
| 5 | ffmpeg.input(filename).output("test.mp4") | 7 | filename: str, |
| 8 | output: str, | ||
| 9 | duration: int, | ||
| 10 | no_sound: bool, | ||
| 11 | start: int | None, | ||
| 12 | end: int | None, | ||
| 13 | ) -> None: | ||
| 14 | if not exists(output): | ||
| 15 | makedirs(output) | ||
| 16 | elif not isdir(output): | ||
| 17 | print("Output is not a directory") | ||
| 18 | exit(1) | ||
| 19 | process = Popen( | ||
| 20 | [ | ||
| 21 | "ffmpeg", | ||
| 22 | "-y", | ||
| 23 | # Input file | ||
| 24 | *("-i", filename), | ||
| 25 | # Start point | ||
| 26 | *(("-ss", str(start)) if start is not None else ()), | ||
| 27 | # End point | ||
| 28 | *(("-to", str(end)) if end is not None else ()), | ||
| 29 | # Codec | ||
| 30 | *("-c:v", "libx264"), | ||
| 31 | *(("-an",) if no_sound else ("-c:a", "mp3")), | ||
| 32 | # Video centring | ||
| 33 | *( | ||
| 34 | "-vf", | ||
| 35 | "scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:-1:-1,setsar=1", | ||
| 36 | ), | ||
| 37 | # Segment splitter | ||
| 38 | *("-f", "segment"), | ||
| 39 | *("-segment_time", str(duration)), | ||
| 40 | *("-reset_timestamps", "1"), | ||
| 41 | *("-force_key_frames", f"expr:gte(t,n_forced*{duration})"), | ||
| 42 | # Output | ||
| 43 | join(output, "%d.mp4"), | ||
| 44 | ] | ||
| 45 | ) | ||
| 46 | |||
| 47 | exit_code = process.wait() | ||
| 48 | if exit_code != 0: | ||
| 49 | exit(exit_code) | ||
