videopython 0.1.41__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of videopython might be problematic. Click here for more details.

Files changed (39) hide show
  1. videopython-0.2.1/.gitignore +140 -0
  2. videopython-0.2.1/PKG-INFO +130 -0
  3. {videopython-0.1.41 → videopython-0.2.1}/README.md +41 -1
  4. videopython-0.2.1/pyproject.toml +88 -0
  5. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/transforms.py +18 -18
  6. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/video.py +101 -58
  7. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/generation/__init__.py +2 -1
  8. videopython-0.2.1/src/videopython/generation/audio.py +56 -0
  9. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/generation/video.py +1 -1
  10. videopython-0.2.1/src/videopython/py.typed +0 -0
  11. videopython-0.2.1/src/videopython/utils/__init__.py +0 -0
  12. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/utils/image.py +1 -1
  13. videopython-0.1.41/PKG-INFO +0 -283
  14. videopython-0.1.41/pyproject.toml +0 -43
  15. videopython-0.1.41/requirements-dev.txt +0 -7
  16. videopython-0.1.41/requirements-generation.txt +0 -4
  17. videopython-0.1.41/requirements.txt +0 -6
  18. videopython-0.1.41/setup.cfg +0 -4
  19. videopython-0.1.41/src/videopython/generation/audio.py +0 -22
  20. videopython-0.1.41/src/videopython.egg-info/PKG-INFO +0 -283
  21. videopython-0.1.41/src/videopython.egg-info/SOURCES.txt +0 -31
  22. videopython-0.1.41/src/videopython.egg-info/dependency_links.txt +0 -1
  23. videopython-0.1.41/src/videopython.egg-info/requires.txt +0 -21
  24. videopython-0.1.41/src/videopython.egg-info/top_level.txt +0 -1
  25. videopython-0.1.41/tests/test_compose.py +0 -35
  26. videopython-0.1.41/tests/test_effects.py +0 -71
  27. videopython-0.1.41/tests/test_transforms.py +0 -69
  28. videopython-0.1.41/tests/test_transitions.py +0 -40
  29. videopython-0.1.41/tests/test_utils.py +0 -11
  30. videopython-0.1.41/tests/test_video.py +0 -135
  31. {videopython-0.1.41 → videopython-0.2.1}/LICENSE +0 -0
  32. {videopython-0.1.41/src/videopython/base → videopython-0.2.1/src/videopython}/__init__.py +0 -0
  33. {videopython-0.1.41/src/videopython/utils → videopython-0.2.1/src/videopython/base}/__init__.py +0 -0
  34. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/compose.py +0 -0
  35. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/effects.py +0 -0
  36. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/exceptions.py +0 -0
  37. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/base/transitions.py +0 -0
  38. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/generation/image.py +0 -0
  39. {videopython-0.1.41 → videopython-0.2.1}/src/videopython/utils/common.py +0 -0
@@ -0,0 +1,140 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
90
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
91
+ # install all needed dependencies.
92
+ #Pipfile.lock
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ .env
106
+ .venv
107
+ env/
108
+ venv/
109
+ ENV/
110
+ env.bak/
111
+ venv.bak/
112
+
113
+ # Spyder project settings
114
+ .spyderproject
115
+ .spyproject
116
+
117
+ # Rope project settings
118
+ .ropeproject
119
+
120
+ # mkdocs documentation
121
+ /site
122
+
123
+ # mypy
124
+ .mypy_cache/
125
+ .dmypy.json
126
+ dmypy.json
127
+
128
+ # type checker
129
+ .pyre/
130
+ .mypy_cache/
131
+
132
+ # Random shit
133
+ *.ipynb
134
+ .vscode
135
+ *.csv
136
+
137
+ # Data directories
138
+ data/downloaded/*.mp4
139
+ data/exported/*.mp4
140
+ !data/exported/example.mp4
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.3
2
+ Name: videopython
3
+ Version: 0.2.1
4
+ Summary: Minimal video generation and processing library.
5
+ Project-URL: Homepage, https://github.com/bartwojtowicz/videopython/
6
+ Project-URL: Repository, https://github.com/bartwojtowicz/videopython/
7
+ Project-URL: Documentation, https://github.com/bartwojtowicz/videopython/
8
+ Author-email: Bartosz Wójtowicz <bartoszwojtowicz@outlook.com>, Bartosz Rudnikowicz <bartoszrudnikowicz840@gmail.com>, Piotr Pukisz <piotr.pukisz@gmail.com>
9
+ License: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: editing,generation,movie,opencv,python,video,videopython
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Python: <3.13,>=3.10
18
+ Requires-Dist: numpy>=1.25.2
19
+ Requires-Dist: opencv-python>=4.9.0.80
20
+ Requires-Dist: pillow>=10.3.0
21
+ Requires-Dist: pydub>=0.25.1
22
+ Requires-Dist: tqdm>=4.66.3
23
+ Provides-Extra: dev
24
+ Requires-Dist: black==24.3.0; extra == 'dev'
25
+ Requires-Dist: isort==5.12.0; extra == 'dev'
26
+ Requires-Dist: mypy==1.8.0; extra == 'dev'
27
+ Requires-Dist: pydub-stubs==0.25.1.1; extra == 'dev'
28
+ Requires-Dist: pytest==7.4.0; extra == 'dev'
29
+ Requires-Dist: types-pillow==10.2.0.20240213; extra == 'dev'
30
+ Requires-Dist: types-tqdm==4.66.0.20240106; extra == 'dev'
31
+ Provides-Extra: generation
32
+ Requires-Dist: accelerate>=0.29.2; extra == 'generation'
33
+ Requires-Dist: diffusers>=0.26.3; extra == 'generation'
34
+ Requires-Dist: torch>=2.1.0; extra == 'generation'
35
+ Requires-Dist: transformers>=4.38.1; extra == 'generation'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # About
39
+
40
+ Minimal video generation and processing library.
41
+
42
+ ## Setup
43
+
44
+ ### Install ffmpeg
45
+ ```bash
46
+ # Install with brew for MacOS:
47
+ brew install ffmpeg
48
+ # Install with apt-get for Ubuntu:
49
+ sudo apt-get install ffmpeg
50
+ ```
51
+
52
+ ### Install with pip
53
+ ```bash
54
+ pip install videopython[generation]
55
+ ```
56
+ > You can install without `[generation]` dependencies for basic video handling and processing.
57
+ > The funcionalities found in `videopython.generation` won't work.
58
+
59
+ ## Basic Usage
60
+
61
+ ### Video handling
62
+
63
+ ```python
64
+ from videopython.base.video import Video
65
+
66
+ # Load videos and print metadata
67
+ video1 = Video.from_path("tests/test_data/fast_benchmark.mp4")
68
+ print(video1)
69
+
70
+ video2 = Video.from_path("tests/test_data/slow_benchmark.mp4")
71
+ print(video2)
72
+
73
+ # Define the transformations
74
+ from videopython.base.transforms import CutSeconds, ResampleFPS, Resize, TransformationPipeline
75
+
76
+ pipeline = TransformationPipeline(
77
+ [CutSeconds(start=1.5, end=6.5), ResampleFPS(fps=30), Resize(width=1000, height=1000)]
78
+ )
79
+ video1 = pipeline.run(video1)
80
+ video2 = pipeline.run(video2)
81
+
82
+ # Combine videos, add audio and save
83
+ from videopython.base.transitions import FadeTransition
84
+
85
+ fade = FadeTransition(effect_time_seconds=3.0)
86
+ video = fade.apply(videos=(video1, video2))
87
+ video.add_audio_from_file("tests/test_data/test_audio.mp3")
88
+
89
+ savepath = video.save()
90
+ ```
91
+
92
+ ### Video Generation
93
+
94
+ > Using Nvidia A40 or better is recommended for the `videopython.generation` module.
95
+ ```python
96
+ # Generate image and animate it
97
+ from videopython.generation import ImageToVideo
98
+ from videopython.generation import TextToImage
99
+ from videopython.generation import TextToMusic
100
+
101
+ image = TextToImage().generate_image(prompt="Golden Retriever playing in the park")
102
+ video = ImageToVideo().generate_video(image=image, fps=24)
103
+
104
+ # Video generation directly from prompt
105
+ from videopython.generation import TextToVideo
106
+ video_gen = TextToVideo()
107
+ video = video_gen.generate_video("Dogs playing in the snow")
108
+ for _ in range(10):
109
+ video += video_gen.generate_video("Dogs playing in the snow")
110
+
111
+ # Cut the first 2 seconds
112
+ from videopython.base.transforms import CutSeconds
113
+ transformed_video = CutSeconds(start_second=0, end_second=2).apply(video.copy())
114
+
115
+ # Upsample to 30 FPS
116
+ from videopython.base.transforms import ResampleFPS
117
+ transformed_video = ResampleFPS(new_fps=30).apply(transformed_video)
118
+
119
+ # Resize to 1000x1000
120
+ from videopython.base.transforms import Resize
121
+ transformed_video = Resize(width=1000, height=1000).apply(transformed_video)
122
+
123
+ # Add generated music
124
+ # MusicGen cannot generate more than 1503 tokens (~30seconds of audio)
125
+ text_to_music = TextToMusic()
126
+ audio = text_to_music.generate_audio("Happy dogs playing together in a park", max_new_tokens=256)
127
+ transformed_video.add_audio(audio=audio)
128
+
129
+ filepath = transformed_video.save()
130
+ ```
@@ -20,12 +20,46 @@ pip install videopython[generation]
20
20
  > The funcionalities found in `videopython.generation` won't work.
21
21
 
22
22
  ## Basic Usage
23
- > Using Nvidia A40 or better is recommended for the `videopython.generation` module.
23
+
24
+ ### Video handling
24
25
 
26
+ ```python
27
+ from videopython.base.video import Video
28
+
29
+ # Load videos and print metadata
30
+ video1 = Video.from_path("tests/test_data/fast_benchmark.mp4")
31
+ print(video1)
32
+
33
+ video2 = Video.from_path("tests/test_data/slow_benchmark.mp4")
34
+ print(video2)
35
+
36
+ # Define the transformations
37
+ from videopython.base.transforms import CutSeconds, ResampleFPS, Resize, TransformationPipeline
38
+
39
+ pipeline = TransformationPipeline(
40
+ [CutSeconds(start=1.5, end=6.5), ResampleFPS(fps=30), Resize(width=1000, height=1000)]
41
+ )
42
+ video1 = pipeline.run(video1)
43
+ video2 = pipeline.run(video2)
44
+
45
+ # Combine videos, add audio and save
46
+ from videopython.base.transitions import FadeTransition
47
+
48
+ fade = FadeTransition(effect_time_seconds=3.0)
49
+ video = fade.apply(videos=(video1, video2))
50
+ video.add_audio_from_file("tests/test_data/test_audio.mp3")
51
+
52
+ savepath = video.save()
53
+ ```
54
+
55
+ ### Video Generation
56
+
57
+ > Using Nvidia A40 or better is recommended for the `videopython.generation` module.
25
58
  ```python
26
59
  # Generate image and animate it
27
60
  from videopython.generation import ImageToVideo
28
61
  from videopython.generation import TextToImage
62
+ from videopython.generation import TextToMusic
29
63
 
30
64
  image = TextToImage().generate_image(prompt="Golden Retriever playing in the park")
31
65
  video = ImageToVideo().generate_video(image=image, fps=24)
@@ -49,5 +83,11 @@ transformed_video = ResampleFPS(new_fps=30).apply(transformed_video)
49
83
  from videopython.base.transforms import Resize
50
84
  transformed_video = Resize(width=1000, height=1000).apply(transformed_video)
51
85
 
86
+ # Add generated music
87
+ # MusicGen cannot generate more than 1503 tokens (~30seconds of audio)
88
+ text_to_music = TextToMusic()
89
+ audio = text_to_music.generate_audio("Happy dogs playing together in a park", max_new_tokens=256)
90
+ transformed_video.add_audio(audio=audio)
91
+
52
92
  filepath = transformed_video.save()
53
93
  ```
@@ -0,0 +1,88 @@
1
+ [project]
2
+ name = "videopython"
3
+ version = "0.2.1"
4
+ description = "Minimal video generation and processing library."
5
+ authors = [
6
+ { name = "Bartosz Wójtowicz", email = "bartoszwojtowicz@outlook.com" },
7
+ { name = "Bartosz Rudnikowicz", email = "bartoszrudnikowicz840@gmail.com" },
8
+ { name = "Piotr Pukisz", email = "piotr.pukisz@gmail.com" }
9
+ ]
10
+ license = { text = "Apache-2.0" }
11
+ readme = "README.md"
12
+ requires-python = ">=3.10, <3.13"
13
+ keywords = ["python", "videopython", "video", "movie", "opencv", "generation", "editing"]
14
+ classifiers = [
15
+ "License :: OSI Approved :: Apache Software License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Operating System :: OS Independent",
20
+ ]
21
+
22
+ dependencies = [
23
+ "numpy>=1.25.2",
24
+ "opencv-python>=4.9.0.80",
25
+ "pillow>=10.3.0",
26
+ "pydub>=0.25.1",
27
+ "tqdm>=4.66.3",
28
+ ]
29
+
30
+ [project.optional-dependencies]
31
+ dev = [
32
+ "black==24.3.0",
33
+ "isort==5.12.0",
34
+ "mypy==1.8.0",
35
+ "pytest==7.4.0",
36
+ "types-Pillow==10.2.0.20240213",
37
+ "types-tqdm==4.66.0.20240106",
38
+ "pydub-stubs==0.25.1.1",
39
+ ]
40
+ generation = [
41
+ "accelerate>=0.29.2",
42
+ "diffusers>=0.26.3",
43
+ "torch>=2.1.0",
44
+ "transformers>=4.38.1",
45
+ ]
46
+
47
+ [project.urls]
48
+ Homepage = "https://github.com/bartwojtowicz/videopython/"
49
+ Repository = "https://github.com/bartwojtowicz/videopython/"
50
+ Documentation = "https://github.com/bartwojtowicz/videopython/"
51
+
52
+ [tool.rye]
53
+ managed = true
54
+ dev-dependencies = [
55
+ "black==24.3.0",
56
+ "isort==5.12.0",
57
+ "mypy==1.8.0",
58
+ "pytest==7.4.0",
59
+ "types-Pillow==10.2.0.20240213",
60
+ "types-tqdm==4.66.0.20240106",
61
+ "pydub-stubs==0.25.1.1",
62
+ ]
63
+
64
+ [tool.rye.scripts]
65
+ test-unit = "pytest"
66
+ test-type = "mypy src"
67
+ test-static = { chain = [
68
+ "black src -l 120 --check",
69
+ "isort src --profile black --check"
70
+ ]}
71
+
72
+ [build-system]
73
+ requires = ["hatchling"]
74
+ build-backend = "hatchling.build"
75
+
76
+ [tool.hatch.build.targets.wheel]
77
+ packages = ["src/videopython"]
78
+
79
+ [tool.hatch.build.targets.sdist]
80
+ include = ["src/videopython", "src/videopython/py.typed"]
81
+
82
+ [tool.mypy]
83
+ mypy_path = "stubs"
84
+
85
+ [tool.pytest]
86
+ testpaths = ["src/tests"]
87
+ python_files = ["test_*.py"]
88
+ addopts = "-v --tb=short"
@@ -53,22 +53,22 @@ class TransformationPipeline:
53
53
 
54
54
 
55
55
  class CutFrames(Transformation):
56
- def __init__(self, start_frame: int, end_frame: int):
57
- self.start_frame = start_frame
58
- self.end_frame = end_frame
56
+ def __init__(self, start: int, end: int):
57
+ self.start = start
58
+ self.end = end
59
59
 
60
60
  def apply(self, video: Video) -> Video:
61
- video = video[self.start_frame : self.end_frame]
61
+ video = video[self.start : self.end]
62
62
  return video
63
63
 
64
64
 
65
65
  class CutSeconds(Transformation):
66
- def __init__(self, start_second: float | int, end_second: float | int):
67
- self.start_second = start_second
68
- self.end_second = end_second
66
+ def __init__(self, start: float | int, end: float | int):
67
+ self.start = start
68
+ self.end = end
69
69
 
70
70
  def apply(self, video: Video) -> Video:
71
- video = video[round(self.start_second * video.fps) : round(self.end_second * video.fps)]
71
+ video = video[round(self.start * video.fps) : round(self.end * video.fps)]
72
72
  return video
73
73
 
74
74
 
@@ -112,18 +112,18 @@ class Resize(Transformation):
112
112
 
113
113
 
114
114
  class ResampleFPS(Transformation):
115
- def __init__(self, new_fps: int | float):
116
- self.new_fps = float(new_fps)
115
+ def __init__(self, fps: int | float):
116
+ self.fps = float(fps)
117
117
 
118
118
  def _downsample(self, video: Video) -> Video:
119
- target_frame_count = int(len(video.frames) * (self.new_fps / video.fps))
119
+ target_frame_count = int(len(video.frames) * (self.fps / video.fps))
120
120
  new_frame_indices = np.round(np.linspace(0, len(video.frames) - 1, target_frame_count)).astype(int)
121
121
  video.frames = video.frames[new_frame_indices]
122
- video.fps = self.new_fps
122
+ video.fps = self.fps
123
123
  return video
124
124
 
125
125
  def _upsample(self, video: Video) -> Video:
126
- target_frame_count = int(len(video.frames) * (self.new_fps / video.fps))
126
+ target_frame_count = int(len(video.frames) * (self.fps / video.fps))
127
127
  new_frame_indices = np.linspace(0, len(video.frames) - 1, target_frame_count)
128
128
  new_frames = []
129
129
  for i in tqdm(range(len(new_frame_indices) - 1)):
@@ -134,17 +134,17 @@ class ResampleFPS(Transformation):
134
134
  ]
135
135
  new_frames.append(new_frame.astype(np.uint8))
136
136
  video.frames = np.array(new_frames, dtype=np.uint8)
137
- video.fps = self.new_fps
137
+ video.fps = self.fps
138
138
  return video
139
139
 
140
140
  def apply(self, video: Video) -> Video:
141
- if video.fps == self.new_fps:
141
+ if video.fps == self.fps:
142
142
  return video
143
- elif video.fps > self.new_fps:
144
- print(f"Downsampling video from {video.fps} to {self.new_fps} FPS.")
143
+ elif video.fps > self.fps:
144
+ print(f"Downsampling video from {video.fps} to {self.fps} FPS.")
145
145
  video = self._downsample(video)
146
146
  else:
147
- print(f"Upsampling video from {video.fps} to {self.new_fps} FPS.")
147
+ print(f"Upsampling video from {video.fps} to {self.fps} FPS.")
148
148
  video = self._upsample(video)
149
149
  return video
150
150