Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it more useable out of the box #1

Merged
merged 22 commits into from
May 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
79bb2ac
build: rework packaging to PEP517 standard with an src layout and exe…
lrq3000 May 1, 2023
88068cd
build: add a few more trove classifiers
lrq3000 May 1, 2023
12630a9
build: rename gestalt.py to videogestalt.py and fix build and entry p…
lrq3000 May 1, 2023
b9c12ab
feat: can specify custom output path (by default resolves to local fi…
lrq3000 May 2, 2023
b4f00e7
feat: default to input file extension if none is provided with -v
lrq3000 May 2, 2023
6c78a01
docs: how to build
lrq3000 May 2, 2023
c122f6d
docs: how to install in edit mode
lrq3000 May 2, 2023
69ea75d
docs: contributors (necessary for copyright/copyleft)
lrq3000 May 2, 2023
0c5ec81
fix: retrocompatibility with older pip versions
lrq3000 May 7, 2023
d2157f9
feat: append .gif extension only if not already present + update help…
lrq3000 May 7, 2023
9966251
tests: add a simple unit test + simplify example in README + bump v0.2.3
lrq3000 May 7, 2023
321fa72
tests: add continuous integration via GitHub Actions
lrq3000 May 7, 2023
4ab673d
tests: add an empty requirements.txt + add test optional dependencies
lrq3000 May 7, 2023
e8c1a98
fix: setuptools complaining of two independent building config files
lrq3000 May 7, 2023
1abeb14
build: exclude tests from being bundled (add MANIFEST.in)
lrq3000 May 7, 2023
a58e3e2
tests: reduce number of target python versions (tests are slow and en…
lrq3000 May 7, 2023
679905b
tests: ensure line returns are not converted to Windows style when gi…
lrq3000 May 7, 2023
bc833db
tests: remove unrecognized parameter
lrq3000 May 7, 2023
ccf2bc8
tests: oopsie: fix test by adding expected result
lrq3000 May 7, 2023
4bac9ba
tests: remove video tests for now because it is not reproducible + li…
lrq3000 May 7, 2023
916b50c
tests: ensure meta tests are run
lrq3000 May 7, 2023
97c23a7
build: add a continuous deployment workflow through GitHub Actions
lrq3000 May 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Simple .gitattributes that disables any text end-of-line normalization/conversion
# `-text` still allows diffs for text types detected by git heuristics, contrary to `binary`
# This avoids issues with binary files eof being converted when using `pip install git+...`
# More templates can be found at: https://github.com/alexkaratarakis/gitattributes

* -text
67 changes: 67 additions & 0 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# This workflow will install Python dependencies and run tests with a variety of Python versions
# It uses the Python Package GitHub Actions workflow.
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
# and https://www.youtube.com/watch?v=l6fV09z5XHk

name: ci-build

on:
push:
branches:
- main # $default-branch only works in Workflows templates, not in Workflows, see https://stackoverflow.com/questions/64781462/github-actions-default-branch-variable
pull_request:
branches:
- main

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.x", pypy-3.9] # check the list of versions: https://github.com/actions/python-versions/releases and https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md -- note that "*" represents the latest stable version of Python, while "3.x" is the latest stable version of Python in the v3 branch.
os: [ ubuntu-latest, windows-latest, macos-latest ] # jobs that run on Windows and macOS runners that GitHub hosts consume minutes at 2 and 10 times the rate that jobs on Linux runners consume respectively. But it's free for public OSS repositories.
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
# You can test your matrix by printing the current Python version
- name: Display Python version
run: |
python -c "import sys; print(sys.version)"
- name: Upgrade pip
run: |
python -m pip install --upgrade pip
- uses: FedericoCarboni/setup-ffmpeg@v2
id: setup-ffmpeg
- name: Install this module
run: |
python -m pip install --upgrade --editable .[test,testmeta] --verbose --use-pep517
- name: Test with pytest
run: |
coverage run --branch -m pytest -v
coverage report -m
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos, but still advised to avoid rate-limiting API by GitHub which makes the upload fails randomly: https://community.codecov.com/t/upload-issues-unable-to-locate-build-via-github-actions-api/3954/9 and https://github.com/codecov/codecov-action/issues/598
#directory: ./coverage/reports/
env_vars: OS,PYTHON
fail_ci_if_error: true
#files: ./coverage1.xml,./coverage2.xml
flags: unittests
name: codecov-umbrella
verbose: true
- name: Build sdist (necessary for the other tests below)
if: ${{ matrix.python-version == '3.x' }}
run: python -sBm build
- name: Twine check
if: ${{ matrix.python-version == '3.x' }}
run: |
twine check "dist/*"
- name: pyproject.toml validity
if: ${{ matrix.python-version == '3.x' }}
run: validate-pyproject pyproject.toml -v
108 changes: 108 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# This workflow will test the module and then upload to PyPi, when triggered by the creation of a new GitHub Release
# It uses the Python Package GitHub Actions workflow.
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
# and https://www.youtube.com/watch?v=l6fV09z5XHk
# and https://py-pkgs.org/08-ci-cd#uploading-to-testpypi-and-pypi

name: ci-cd

# Build only on creation of new releases
on:
# push: # build on every commit push
# pull_request: # build on every pull request
release: # build on every releases
types:
- published # use published, not released and prereleased, because prereleased is not triggered if created from a draft: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release

jobs:
testbuild:
name: Unit test and building
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ["3.x"] # check the list of versions: https://github.com/actions/python-versions/releases and https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md -- note that "*" represents the latest stable version of Python
os: [ ubuntu-latest, windows-latest, macos-latest ] # jobs that run on Windows and macOS runners that GitHub hosts consume minutes at 2 and 10 times the rate that jobs on Linux runners consume respectively. But it's free for public OSS repositories.
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
# You can test your matrix by printing the current Python version
- name: Display Python version
run: |
python -c "import sys; print(sys.version)"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- uses: FedericoCarboni/setup-ffmpeg@v2
id: setup-ffmpeg
- name: Install this module
run: |
python -m pip install --upgrade --editable .[test] --verbose --use-pep517
- name: Test with pytest
run: |
coverage run --branch -m pytest -v
coverage report -m
- name: Build source distribution and wheel
run: |
python -m pip install --upgrade build
python -sBm build
- name: Save dist/ content for reuse in other GitHub Workflow blocks
uses: actions/upload-artifact@v3
with:
path: dist/*

upload_test_pypi: # Upload to TestPyPi first to ensure that the release is OK (we will try to download it and install it afterwards), as recommended in https://py-pkgs.org/08-ci-cd#uploading-to-testpypi-and-pypi
name: Upload to TestPyPi
needs: [testbuild]
runs-on: ubuntu-latest
steps:
- name: Unpack default artifact into dist/
uses: actions/download-artifact@v3
with:
# unpacks default artifact into dist/
# if `name: artifact` is omitted, the action will create extra parent dir
name: artifact
path: dist

- name: Upload to TestPyPi
uses: pypa/[email protected]
with:
user: __token__
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
# To test: repository_url: https://test.pypi.org/legacy/ # and also change token: ${{ secrets.PYPI_API_TOKEN }} to secrets.TEST_PYPI_API_TOKEN # for more infos on registering and using TestPyPi, read: https://py-pkgs.org/08-ci-cd#uploading-to-testpypi-and-pypi -- remove the repository_url to upload to the real PyPi

- name: Test install from TestPyPI
run: |
python -m pip install --upgrade pip
pip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple \
videogestalt

upload_pypi: # Upload to the real PyPi if everything else worked before, as suggested in: https://py-pkgs.org/08-ci-cd#uploading-to-testpypi-and-pypi
name: Upload to the real PyPi
needs: [testbuild, upload_test_pypi]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v3
with:
# unpacks default artifact into dist/
# if `name: artifact` is omitted, the action will create extra parent dir
name: artifact
path: dist

- uses: pypa/[email protected]
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}

- name: Test install from PyPI
run: |
python -m pip install --upgrade pip
pip uninstall videogestalt -y
pip install --upgrade videogestalt
76 changes: 76 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '27 18 * * 3'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Cannot yet fully replace MANIFEST.in by pyproject.toml if we use setuptools, see: https://github.com/pypa/setuptools/issues/3341
# Test suite
recursive-exclude tests *.py # unit test scripts
72 changes: 55 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,89 @@
# Video Gestalt

[![gestalt-Vespa-Scooter-Commercial ia mp4][1]][3]
[![gestalt-Vespa-Scooter-Commercial ia mp4][1]][2]

Presents a video in a summary form that shows the entire video at once as an array of moving video thumbnails.

## Description

Video Gestalt presents a condensed video array, showing the entire video at once as moving video thumbnails.

The above is an example of the Video Gestalt for a 50-second commercial for Vesta scooters. (Click the Video Gestalt to see the original video.)

As you can see, it is a looping video with moving thumbnails of the original video. In one second, you can see every frame of the original video at a glance, without any discontinuities as it loops. This is done by arranging that each thumbnail slides over exactly its width in one loop so that the next thumbnail takes over seamlessly.

Hence, the video gestalts can be read in two ways: 1- an overall quick glance shows all the scenes of the entire video, 2- by focusing on one animated thumbnail, we can watch the entire video, by starting in the upper left corner, and following to the right, then descending one block lower and moving from right to left, then descending one block and moving left to right again, etc.

A longer explanation is available in [this blog post](https://eamonn.org/video-gestalt-one-glance-overview-of-a-video).

## Installation

So far this has only been tested on Linux and Chrome OS, but it will likely work on MacOS too, and maybe even on Windows.
So far this has been tested on Linux, Chrome OS and Windows, but it will likely work on MacOS too.

The only file you need from this repo is `gestalt.py`. You can grab this however you want, and make it executable. For example, do the following from the command line:
To install, simply use `pip`:

```bash
wget https://raw.githubusercontent.com/eobrain/videogestalt/main/gestalt.py
chmod +x gestalt.py
pip install --upgrade videogestalt
```

If they are not already installed, you will need to install `python3` and the corresponding Python package manager `pip`.

If they are not already installed, you will need to install `python3` and the corresponding Python package manager `pip` beforehand.

On Linux and friends you might be able to do this like so:
```bash
sudo apt-get install python3 python3-pip
```

You will need to install the `moviepy` Python library:
If you get an error, please ensure you are using the latest `pip` version, as older versions may not support PEP517 Python packages:

```bash
pip install moviepy
pip install --upgrade pip
```


## Usage

Put the `gestalt.py` in the same directory as an input video file `test.mp4`.
An executable binary `videogestalt` is automatically installed in the local environment.

To generate a video file:

```bash
videogestalt -i countdown.mp4 -o countdown-gestalt --video
```

To generate an animated GIF (warning, output can be large):

```bash
videogestalt -i countdown.mp4 -o countdown-gestalt --gif
```

The application can also be used as a Python module:

```python
>>> from videogestalt import videogestalt as vg
>>> vg.main('-i countdown.mp4 -o countdown-gestalt --gif')
```

Note: if the repository is cloned, there is an example `countdown.mp4` video in `tests/examples`.

## Building

Generate a video file:
The module can be built with PEP517 standard tools, such as `pypa/build`:

```bash
./gestalt.py -i test.mp4 -v
python -sBm build .
```

Generate an animated GIF (warning, can be large):
It can also be installed in development/editable mode after cloning this git repository:

```bash
./gestalt.py -i test.mp4 -g
pip install --upgrade -e .
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me (using Python 3.9.2 on Linux) this failed with

ERROR: File "setup.py" not found. Directory cannot be installed in editable mode: /home/eobrain/src/lrq3000
(A "pyproject.toml" file was found, but editable mode currently requires a setup.py based build.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmm I guess your pip version is not updated to the latest, as it should be fixed since pip versions of last year. Nevertheless, I have implemented a workaround now, please retry with my updated PR and let me know if this works :-)

```
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest adding the commands to run the videogestalt command from the local development version

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from the git cloning, this is the only command that should be needed. Now that I fixed the ERROR: File "setup.py" not found, this should work as expected :-)


[1]: https://user-images.githubusercontent.com/179320/226146985-d67db97e-bcd6-4377-a1da-cc6020135d84.gif
[3]: https://ia904607.us.archive.org/11/items/vespa-scooter-commercial/Vespa%20Scooter%20Commercial.mp4
## License

Created by Eamonn O'Brien-Strain.

Licensed under the Mozilla Public License 2.0

[1]: https://github.com/eobrain/videogestalt/master/resources/vespa-commercial-gestalt.gif
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular reason for pulling the example GIF output into the repo? If not, I suggest leaving it in its original position in GitHib static images.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes usually when an image is meant to be included in the README and not just in the static website, I prefer to include them in the repository to be more future proof, as URLs of static sites may change or be down at any point in the future (it already happened in the past). There is also another pragmatic reason, it's because I don't know where the image is stored currently (I cannot find the source branch from which the image is pushed to GitHub pages?).

[2]: https://ia904607.us.archive.org/11/items/vespa-scooter-commercial/Vespa%20Scooter%20Commercial.mp4

Loading