From 5748265aa0d44e84c57665cc3ea37fd3a20e1c87 Mon Sep 17 00:00:00 2001 From: Ryan Fox Date: Tue, 6 Sep 2022 23:29:33 -0500 Subject: [PATCH 1/4] initial commit --- LICENSE | 21 ++++++ README.md | 75 ++++++++++++++++++++ setup.py | 33 +++++++++ video_to_sqlite/__init__.py | 0 video_to_sqlite/callback.py | 30 ++++++++ video_to_sqlite/cli.py | 134 ++++++++++++++++++++++++++++++++++++ 6 files changed, 293 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 setup.py create mode 100644 video_to_sqlite/__init__.py create mode 100644 video_to_sqlite/callback.py create mode 100644 video_to_sqlite/cli.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..32f50f8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +ANTI-CAPITALIST SOFTWARE LICENSE (v 1.4) + +Copyright © 2022 Ryan Fox + +This is anti-capitalist software, released for free use by individuals and organizations that do not operate by capitalist principles. + +Permission is hereby granted, free of charge, to any person or organization (the "User") obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, merge, distribute, and/or sell copies of the Software, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in all copies or modified versions of the Software. + +2. The User is one of the following: +a. An individual person, laboring for themselves +b. A non-profit organization +c. An educational institution +d. An organization that seeks shared profit for all of its members, and allows non-members to set the cost of their labor + +3. If the User is an organization with owners, then all owners are workers and all workers are owners with equal equity and/or equal vote. + +4. If the User is an organization, then the User is not law enforcement or military, or working for or under either. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c460bb0 --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# video-to-sqlite + +[![PyPI](https://img.shields.io/pypi/v/video-to-sqlite.svg)](https://pypi.org/project/video-to-sqlite/) + +Load data about a video file into SQLite + +## Installation + +Install this tool using `pip`: + + pip install video-to-sqlite + +## Usage + +To create a SQLite database with metadata about a video, run: + + video-to-sqlite videos.db my_video.mp4 + +The tool will create two tables: `videos` and `frames`. If `videos.db` already exists, the video will be added to the +`videos` table. + +To create the tables with a prefix, use `--prefix prefix`. For example: + + video-to-sqlite videos.db cool_video.mp4 --prefix cool_ + +This will create tables called `cool_videos` and `cool_frames`. + +### Extra processing + +Using the library programatically allows extra columns to be added to the database via a callback. Specify the +`callback` argument to `cli.main()`. + +The function will be called once per frame in the video. It should accept a numpy ndarray as the single argument, and +return a dict. The dict's keys will be added as columns to the DB, and values will be the corresponding values for that +row. + +An example: + +``` +import video_to_sqlite + +def my_callback(frame): + has_a_cat_in_it = ai_cat_image_detector(frame) + return {'cat': has_a_cat_in_it} + +video_to_sqlite.main('my_database.db', 'cool_video.mp4', 'cool_', my_callback) +``` + +See `callback.py` for a working example. + + +## video-to-sqlite --help + +``` +Usage: video-to-sqlite DB_PATH VIDEO_FILE PREFIX + + Load data about Python packages from PyPI into SQLite + + Usage example: + + video-to-sqlite videos.db my_video.mp4 my_ + + Created tables will be videos and frames + + To create tables called cool_videos, cool_frames use + --prefix cool_: + + video-to-sqlite videos.db my_video.mp4 --prefix cool_ + +Options: + --version Show the version and exit. + --prefix TEXT Prefix to use for the created database tables + --help Show this message and exit. + +``` diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..ec2ec94 --- /dev/null +++ b/setup.py @@ -0,0 +1,33 @@ +from setuptools import setup +import os + +VERSION = '0.0.1' + + +def get_long_description(): + with open( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "README.md"), + encoding="utf8", + ) as fp: + return fp.read() + +setup( + name='video-to-sqlite', + description='Load data about a video file into SQLite', + long_description=get_long_description(), + long_description_content_type='text/markdown', + author='Ryan Fox', + url='https://github.com/ryanfox/video-to-sqlite', + project_urls={ + 'Issues': 'https://github.com/ryanfox/video-to-sqlite/issues', + }, + license='ACSL v1.4 (https://anticapitalist.software)', + version=VERSION, + packages=['video_to_sqlite'], + entry_points=""" + [console_scripts] + video-to-sqlite=video_to_sqlite.cli:cli + """, + install_requires=['click', 'sqlite-utils', 'imageio[ffmpeg]'], + python_requires='>=3.7', +) diff --git a/video_to_sqlite/__init__.py b/video_to_sqlite/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/video_to_sqlite/callback.py b/video_to_sqlite/callback.py new file mode 100644 index 0000000..ed2c048 --- /dev/null +++ b/video_to_sqlite/callback.py @@ -0,0 +1,30 @@ +import sys + +from video_to_sqlite import cli + + +def process(frame): + """ + An example of using a callback to add custom columns to a video-to-sqlite db. + Add the highest, lowest, and mean value of the frame to the row. + + :param frame: a numpy ndarray of the video frame + :return: a dict, where keys will be column names and values the cell contents in the db + """ + maximum = frame.max() + minimum = frame.min() + mean = frame.mean() + + return { + 'max': maximum, + 'min': minimum, + 'mean': mean, + } + + +if __name__ == '__main__': + """ + Usage: python callback.py