` tag bounding-box style to the Static FFmpeg binary download links in FFmpeg Installation Doc for better accessibility.
+ - [x] **Maintenance:**
+ * Switched to new Issue GitHub's form schema using YAML:
+ * Added new `bug_report.yaml` Issue GitHub's form schema for Bug Reports.
+ * Added new `idea.yaml` Issue GitHub's form schema for new Ideas.
+ * Added new `question.yaml` Issue GitHub's form schema for Questions.
+ * Deleted old depreciated markdown(`.md`) files.
+ * Polished forms.
+
+??? success "Updates/Improvements"
+ - [x] Maintenance:
+ * Added new patterns to `.gitignore` to ignore vim files.
+ - [x] CI:
+ * Updated `test_FFdecoder_params` unittest to include `with` statement access method.
+ - [x] Setup:
+ * Added new patches for using README.md text as `long_description` metadata.
+ * Implemented new patch to remove GitHub README UI specific text.
+ * Simplified multiple `str.replace` to chained `str.replace` of better readability.
+ * Bumped version to `0.2.3`.
+ - [x] Docs:
+ * Updated recipes to include `with` statement access method.
+ * Updated existing recipes to include `with` statement access method in FFdecoder APIs.
+ * Included new example code of accessing RGB frames using `with` statement access method.
+ * Updated Recipe title to "Accessing RGB frames from a video file" across docs.
+ * Included warning admonition for advising users to always use `trim` with `reverse` filter.
+ * Updated docs text font to `Libre Franklin`.
+ * Updated method description texts and logging messages.
+ * Update icons and admonition messages.
+ * Updated code comments.
+ * Updated `changelog.md`.
+
+??? bug "Bug-fixes"
+ - [x] FFdecoder API:
+ * Fixed Context Manager methods.
+ * Fixed `__enter__` method returning class instance instead of formulating pipeline.
+ * Fixed `__exit__` method calling wrong non-existent method.
+ - [x] Setup:
+ * Fixed missing `comma(,)` in keywords metadata.
+ * Fixed bug in patch string.
+ - [x] Docs:
+ * Fixed typos in code comments.
+ * Fixed several typos in docs.
+
+??? question "Pull Requests"
+ * PR #26
+
+
+
+
+
+## v0.2.2 (2022-08-09)
??? new "New Features"
- [x] **Sourcer API:**
@@ -242,9 +298,9 @@ limitations under the License.
* Updated date/version tag to `12-07-2022`.
* Removed depreciated binaries download links and code.
- [x] Setup:
- * Bumped version to 0.2.1.
+ * Bumped version to `0.2.1`.
- [x] Docs:
- * Updated Changelog.md
+ * Updated `changelog.md`.
??? danger "Breaking Updates/Changes"
- [x] :skull_crossbones: **Implement support for live input devices/sources.**
diff --git a/docs/index.md b/docs/index.md
index 1a9ebb1..0f0d44e 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -23,13 +23,13 @@ limitations under the License.
![DeFFcode](assets/images/deffcode.png#only-light){ loading=lazy }
![DeFFcode](assets/images/deffcode-dark.png#only-dark){ loading=lazy }
-
DeFFcode - A cross-platform **High-performance Video Frames Decoder** that flexibly executes
FFmpeg pipeline inside a subprocess pipe for generating real-time, low-overhead,
lightning fast video frames with robust error-handling
in just a few lines of python code :zap:
+
A cross-platform **:fontawesome-solid-gauge-high: High-performance Video Frames Decoder** that flexibly executes FFmpeg pipeline inside a subprocess pipe for generating real-time, low-overhead,
lightning fast video frames with robust error-handling
in just a few lines of python code :fontawesome-solid-fire-flame-curved:
**==Highly Adaptive== -** DeFFcode APIs implements a **standalone highly-extensible wrapper around [FFmpeg][ffmpeg]** multimedia framework. These APIs **supports a wide-ranging media streams as input** source such as live USB/Virtual/IP camera feeds, regular multimedia files, screen recordings, image sequences, network protocols _(such as HTTP(s), RTP/RSTP, etc.)_, so on and so forth.
-**==Highly Flexible== -** DeFFcode APIs gains an edge over other Wrappers by providing **complete control over the underline pipeline** including **access to almost any FFmpeg specification thinkable** such as specifying framerate, resolution, hardware decoder(s), filtergraph(s), and
pixel-format(s) that are readily **supported by all well known Computer Vision libraries**.
+**==Highly Flexible== -** DeFFcode APIs gains an edge over other Wrappers by providing **complete control over the underline pipeline** including **access to almost any FFmpeg specification thinkable** such as specifying framerate, resolution, hardware decoder(s), filtergraph(s), and pixel-format(s) that are readily **supported by all well known Computer Vision libraries**.
**==Highly Convenient== -** FFmpeg has a steep learning curve especially for users unfamiliar with a command line interface. DeFFcode helps users by keeping the **same [OpenCV-Python](https://docs.opencv.org/4.x/d6/d00/tutorial_py_root.html) _(Python API for OpenCV)_ coding syntax for its APIs**, thereby making it even **easier to learn, create, and develop FFmpeg based apps** in Python.
@@ -43,7 +43,7 @@ Here are some key features that stand out:
- [x] Flexible API with access to almost any FFmpeg specification thinkable.
- [x] Supports a wide-range of media streams/devices/protocols as input source.
- [x] Curated list of well-documented recipes ranging from [**Basic**](recipes/basic/) to [**Advanced**](recipes/advanced/) skill levels.
-- [x] Easy to code **Live [Simple](recipes/basic/transcode-live-frames-simplegraphs/#transcoding-live-simple-filtergraphs) & [Complex](recipes/advanced/transcode-live-frames-complexgraphs/#transcoding-live-complex-filtergraphs) Filtergraphs**. _(Yes, You read it correctly "Real-time"!)_
+- [x] Memory efficient **Live [Simple](recipes/basic/transcode-live-frames-simplegraphs/#transcoding-live-simple-filtergraphs) & [Complex](recipes/advanced/transcode-live-frames-complexgraphs/#transcoding-live-complex-filtergraphs) Filtergraphs**. _(Yes, You read it correctly "Live"!)_
- [x] Lightning fast dedicated **:fontawesome-solid-microchip: GPU-Accelerated Video [Decoding](recipes/advanced/decode-hw-acceleration/#hardware-accelerated-video-decoding) & [Transcoding](recipes/advanced/transcode-hw-acceleration/#hardware-accelerated-video-transcoding)**.
- [x] Enables precise FFmpeg [**Frame Seeking**](recipes/basic/save-keyframe-image/#extracting-key-frames-as-png-image) with pinpoint accuracy.
- [x] Effortless [**Metadata Extraction**](recipes/basic/extract-video-metadata/#extracting-video-metadata) from all streams available in the source.
@@ -192,6 +192,28 @@ It is something I am doing with my own free time. But so much more needs to be d
+## Citation
+
+Here is a Bibtex entry you can use to cite this project in a publication:
+
+[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.6976948.svg)](https://doi.org/10.5281/zenodo.6976948)
+
+```BibTeX
+@software{deffcode,
+ author = {Abhishek Thakur},
+ title = {abhiTronix/deffcode: v0.2.2},
+ month = aug,
+ year = 2022,
+ publisher = {Zenodo},
+ version = {v0.2.2},
+ doi = {10.5281/zenodo.6976948},
+ url = {https://doi.org/10.5281/zenodo.6976948}
+}
+```
+
+
+
+
diff --git a/docs/installation/ffmpeg_install.md b/docs/installation/ffmpeg_install.md
index f0d893a..2204c86 100644
--- a/docs/installation/ffmpeg_install.md
+++ b/docs/installation/ffmpeg_install.md
@@ -51,9 +51,15 @@ If DeFFcode APIs do not receive any input from the user on [**`custom_ffmpeg`**]
### B. Manual Configuration
-* **Download:** You can also manually download the latest Linux Static Binaries(*based on your machine arch(x86/x64)*) from the link below:
-
+* **Download:** You can also manually download the latest Linux Static Binaries _(based on your machine architecture)_ from the link below:
+
+
**:material-file-download: Linux Static Binaries:** http://johnvansickle.com/ffmpeg/
+
* **Assignment:** Then, you can easily assign the custom path to the folder containing FFmpeg executables(`for e.g 'ffmpeg/bin'`) or path of `ffmpeg` executable itself to the [**`custom_ffmpeg`**](../../reference/ffdecoder/params/#custom_ffmpeg) parameter in the DeFFcode APIs.
@@ -82,9 +88,9 @@ If DeFFcode APIs do not receive any input from the user on [**`custom_ffmpeg`**]
* You can also provide a custom save path for auto-downloading **FFmpeg Static Binaries** through exclusive [`-ffmpeg_download_path`](../../reference/sourcer/params/#exclusive-parameters) attribute in Sourcer API.
- ??? question "How to use `-ffmpeg_download_path` attribute in FFdecoder API?
+ ??? question "How to use `-ffmpeg_download_path` attribute in FFdecoder API?"
- `-ffmpeg_download_path` is also available in FFdecoder API through the [`-custom_sourcer_params`](../../reference/ffdecoder/params/#b-exclusive-parameters) attribute of its `ffparams` dictionary parameter
+ `-ffmpeg_download_path` is also available in FFdecoder API through the [`-custom_sourcer_params`](../../reference/ffdecoder/params/#b-exclusive-parameters) attribute of its `ffparams` dictionary parameter.
* If binaries were found at the specified path, DeFFcode APIs automatically skips the Auto-Installation step.
@@ -93,9 +99,15 @@ If DeFFcode APIs do not receive any input from the user on [**`custom_ffmpeg`**]
### B. Manual Configuration
-* **Download:** You can also manually download the latest Windows Static Binaries(*based on your machine arch(x86/x64)*) from the link below:
-
+* **Download:** You can also manually download the latest Windows Static Binaries _(based on your machine arch(x86/x64))_ from the link below:
+
+
**:material-file-download: Windows Static Binaries:** https://ffmpeg.org/download.html#build-windows
+
* **Assignment:** Then, you can easily assign the custom path to the folder containing FFmpeg executables(`for e.g 'C:/foo/Downloads/ffmpeg/bin'`) or path of `ffmpeg.exe` executable itself to the [**`custom_ffmpeg`**](../../reference/ffdecoder/params/#custom_ffmpeg) parameter in the DeFFcode APIs.
@@ -120,9 +132,15 @@ If DeFFcode APIs do not receive any input from the user on [**`custom_ffmpeg`**]
### B. Manual Configuration
-* **Download:** You can also manually download the latest MacOS Static Binaries(*only x64 Binaries*) from the link below:
-
+* **Download:** You can also manually download the latest MacOS Static Binaries _(only x64 Binaries)_ from the link below:
+
+
**:material-file-download: MacOS Static Binaries:** https://ffmpeg.org/download.html#build-mac
+
* **Assignment:** Then, you can easily assign the custom path to the folder containing FFmpeg executables(`for e.g 'ffmpeg/bin'`) or path of `ffmpeg` executable itself to the [**`custom_ffmpeg`**](../../reference/ffdecoder/params/#custom_ffmpeg) parameter in the DeFFcode APIs.
diff --git a/docs/recipes/advanced/decode-hw-acceleration.md b/docs/recipes/advanced/decode-hw-acceleration.md
index 18ba134..d2e0c56 100644
--- a/docs/recipes/advanced/decode-hw-acceleration.md
+++ b/docs/recipes/advanced/decode-hw-acceleration.md
@@ -22,7 +22,9 @@ limitations under the License.
!!! abstract "FFmpeg offer access to dedicated GPU hardware with varying support on different platforms for performing a range of video-related tasks to be completed faster or using less of other resources (particularly CPU)."
-> By default, DeFFcode's FFdecoder API uses the Input Source's video-decoder _(extracted using Sourcer API)_ itself for decoding its input. However, you could easily change the video-decoder to your desired specific [**supported Video-Decoder**](../../reference/ffdecoder/params/#supported-decoders) using the `-vcodec` FFmpeg option by way of its [`ffparams`](../../reference/ffdecoder/params/#ffparams) dictionary parameter. This means easy access to GPU Accelerated Hardware Decoder to get better playback and accelerated video decoding on GPUs that will generate equivalent output to software decoders, but may use less power and CPU to do so.
+> By default, DeFFcode's FFdecoder API uses the Input Source's video-decoder _(extracted using Sourcer API)_ itself for decoding its input. However, you could easily change the video-decoder to your desired specific **supported Video-Decoder** using the `-vcodec` FFmpeg option by way of its [`ffparams`](../../reference/ffdecoder/params/#ffparams) dictionary parameter. This means easy access to GPU Accelerated Hardware Decoder to get better playback and accelerated video decoding on GPUs that will generate equivalent output to software decoders, but may use less power and CPU to do so.
+
+!!! tip "Use `#!sh ffmpeg -decoders` terminal command to lists all FFmpeg supported decoders."
We'll discuss its Hardware-Accelerated Video Decoding capabilities briefly in the following recipes:
diff --git a/docs/recipes/advanced/transcode-art-filtergraphs.md b/docs/recipes/advanced/transcode-art-filtergraphs.md
index cedb1f2..c4b1420 100644
--- a/docs/recipes/advanced/transcode-art-filtergraphs.md
+++ b/docs/recipes/advanced/transcode-art-filtergraphs.md
@@ -126,7 +126,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
@@ -203,7 +203,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
@@ -271,7 +271,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
@@ -339,7 +339,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
diff --git a/docs/recipes/advanced/transcode-hw-acceleration.md b/docs/recipes/advanced/transcode-hw-acceleration.md
index ea1d7d8..4eddb4a 100644
--- a/docs/recipes/advanced/transcode-hw-acceleration.md
+++ b/docs/recipes/advanced/transcode-hw-acceleration.md
@@ -170,7 +170,7 @@ output_params = {
# Define writer with defined parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
diff --git a/docs/recipes/advanced/transcode-live-frames-complexgraphs.md b/docs/recipes/advanced/transcode-live-frames-complexgraphs.md
index 353dce0..d6c989e 100644
--- a/docs/recipes/advanced/transcode-live-frames-complexgraphs.md
+++ b/docs/recipes/advanced/transcode-live-frames-complexgraphs.md
@@ -72,6 +72,8 @@ We'll discuss the transcoding of live complex filtergraphs in the following reci
!!! note "Always use FFdecoder API's [`terminate()`](../../reference/ffdecoder/#deffcode.ffdecoder.FFdecoder.terminate) method at the end to avoid undesired behavior."
+!!! danger "==WriteGear's Compression Mode support for FFdecoder API is currently in beta so you can expect much higher than usual CPU utilization!=="
+
@@ -89,6 +91,8 @@ In this example we will apply a watermark image _(say `watermark.png` with trans
!!! tip "To learn about exclusive `-ffprefixes` & `-clones` parameter. See [Exclusive Parameters ➶](../../reference/ffdecoder/params/#b-exclusive-parameters)"
+!!! alert "Remember to replace `watermark.png` watermark image file-path with yours before using this recipe."
+
```python
# import the necessary packages
from deffcode import FFdecoder
@@ -123,7 +127,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
@@ -160,8 +164,6 @@ writer.close()
In this example we will blend **`10` seconds of Mandelbrot test pattern** _(generated using `lavfi` input virtual device)_ that serves as the "top" layer with **`10` seconds of Image Sequence** that serves as the "bottom" layer, using `blend` filter _(with `heat` blend mode)_, and decode live **BGR24** video frames in FFdecoder API. We'll also be encoding those decoded frames in real-time into lossless video file using WriteGear API with controlled framerate.
-!!! danger "==WriteGear's Compression Mode support for FFdecoder API is currently in beta so you can expect much higher than usual CPU utilization!=="
-
??? tip "Extracting Image Sequences from a video"
**You can use following FFmpeg command to extract sequences of images from a video file `foo.mp4` _(restricted to 12 seconds)_:**
@@ -226,7 +228,7 @@ output_params = {
# Define writer with default parameters and suitable
# output filename for e.g. `output_foo.mp4`
-writer = WriteGear(output_filename="output_foo.mp4", logging=True, **output_params)
+writer = WriteGear(output_filename="output_foo.mp4", **output_params)
# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():
diff --git a/docs/recipes/basic/decode-video-files.md b/docs/recipes/basic/decode-video-files.md
index 3938033..dacd0e6 100644
--- a/docs/recipes/basic/decode-video-files.md
+++ b/docs/recipes/basic/decode-video-files.md
@@ -61,19 +61,19 @@ We'll discuss its video files support and pixel format capabilities briefly in t
-## Capturing RGB frames from a video file
+## Accessing RGB frames from a video file
!!! abstract "The default function of FFdecoder API is to **decode 24-bit RGB video frames** from the given source."
-> FFdecoder API's [`generateFrame()`](../../reference/ffdecoder/#deffcode.ffdecoder.FFdecoder.generateFrame) function can be used both as a **Generator** _(Recommended Approach)_ and **Iterator**.
+> FFdecoder API's [`generateFrame()`](../../reference/ffdecoder/#deffcode.ffdecoder.FFdecoder.generateFrame) function can be used in multiple methods to access RGB frames from a given source, such as **as a Generator** _(Recommended Approach)_, **calling `with` Statement**, and **as a Iterator**.
-In this example we will decode the default **RGB24** video frames from a given Video file _(say `foo.mp4`)_ using both approaches:
+In this example we will decode the default **RGB24** video frames from a given Video file _(say `foo.mp4`)_ using above mentioned accessing methods:
=== "As a Generator (Recommended)"
- !!! quote "This is a recommended approach for faster and safer decoding."
+ !!! quote "This is a recommended approach for faster and error-proof access of decoded frames. We'll use it throughout the recipes."
```python
# import the necessary packages
@@ -98,6 +98,31 @@ In this example we will decode the default **RGB24** video frames from a given V
decoder.terminate()
```
+=== "Calling `with` Statement"
+
+ !!! quote "Calling `with` Statement approach can be used to make the code easier, cleaner, and much more readable. This approach also automatically handles management of `formulate()` and `terminate()` methods in FFdecoder API, so don't need to explicitly call them. See [PEP343 -- The 'with' statement'](https://peps.python.org/pep-0343/) for more information on this approach."
+
+ ```python
+ # import the necessary packages
+ from deffcode import FFdecoder
+ import cv2
+
+ # initialize and formulate the decoder
+ with FFdecoder("foo.mp4") as decoder:
+
+ # grab the BGR24 frames from decoder
+ for frame in decoder.generateFrame():
+
+ # check if frame is None
+ if frame is None:
+ break
+
+ # {do something with the frame here}
+
+ # lets print its shape
+ print(frame.shape) # for e.g. (1080, 1920, 3)
+ ```
+
=== "As a Iterator"
!!! quote "This Iterator Approach bears a close resemblance to **OpenCV-Python** _(Python API for OpenCV)_ coding syntax, thereby easier to learn and remember."
@@ -135,39 +160,74 @@ In this example we will decode the default **RGB24** video frames from a given V
In this example we will decode **OpenCV supported** live **BGR24** video frames from a given Video file _(say `foo.mp4`)_ in FFdecoder API, and preview them using OpenCV Library's `cv2.imshow()` method.
-!!! alert "By default, OpenCV expects `BGR` format frames in its `cv2.imshow()` method."
+!!! alert "By default, OpenCV expects `BGR` format frames in its `cv2.imshow()` method by using two accessing methods."
-```python
-# import the necessary packages
-from deffcode import FFdecoder
-import cv2
+=== "As a Generator (Recommended)"
-# initialize and formulate the decoder for BGR24 pixel format output
-decoder = FFdecoder("foo.mp4", frame_format="bgr24").formulate()
+ ```python
+ # import the necessary packages
+ from deffcode import FFdecoder
+ import cv2
-# grab the BGR24 frames from decoder
-for frame in decoder.generateFrame():
+ # initialize and formulate the decoder for BGR24 pixel format output
+ decoder = FFdecoder("foo.mp4", frame_format="bgr24").formulate()
- # check if frame is None
- if frame is None:
- break
+ # grab the BGR24 frames from decoder
+ for frame in decoder.generateFrame():
- # {do something with the frame here}
-
- # Show output window
- cv2.imshow("Output", frame)
+ # check if frame is None
+ if frame is None:
+ break
+
+ # {do something with the frame here}
+
+ # Show output window
+ cv2.imshow("Output", frame)
+
+ # check for 'q' key if pressed
+ key = cv2.waitKey(1) & 0xFF
+ if key == ord("q"):
+ break
+
+ # close output window
+ cv2.destroyAllWindows()
- # check for 'q' key if pressed
- key = cv2.waitKey(1) & 0xFF
- if key == ord("q"):
- break
+ # terminate the decoder
+ decoder.terminate()
+ ```
+
+=== "Calling `with` Statement"
-# close output window
-cv2.destroyAllWindows()
+ !!! quote "Calling `with` Statement approach can be used to make the code easier, cleaner, and much more readable. This approach also automatically handles management of `formulate()` and `terminate()` methods in FFdecoder API, so don't need to explicitly call them. See [PEP343 -- The 'with' statement'](https://peps.python.org/pep-0343/) for more information on this approach."
-# terminate the decoder
-decoder.terminate()
-```
+ ```python
+ # import the necessary packages
+ from deffcode import FFdecoder
+ import cv2
+
+ # initialize and formulate the decoder for BGR24 pixel format output
+ with FFdecoder("foo.mp4", frame_format="bgr24") as decoder:
+
+ # grab the BGR24 frames from decoder
+ for frame in decoder.generateFrame():
+
+ # check if frame is None
+ if frame is None:
+ break
+
+ # {do something with the frame here}
+
+ # Show output window
+ cv2.imshow("Output", frame)
+
+ # check for 'q' key if pressed
+ key = cv2.waitKey(1) & 0xFF
+ if key == ord("q"):
+ break
+
+ # close output window
+ cv2.destroyAllWindows()
+ ```
diff --git a/docs/recipes/basic/index.md b/docs/recipes/basic/index.md
index ef8fe6d..fa87895 100644
--- a/docs/recipes/basic/index.md
+++ b/docs/recipes/basic/index.md
@@ -52,7 +52,7 @@ The following recipes should be reasonably accessible to beginners of any skill
## Basic :material-movie-play: Decoding Recipes
- [x] **[:material-file-eye: Decoding Video files](../basic/decode-video-files/#decoding-video-files)**
- - [Capturing RGB frames from a video file](../basic/decode-video-files/#capturing-rgb-frames-from-a-video-file)
+ - [Accessing RGB frames from a video file](../basic/decode-video-files/#accessing-rgb-frames-from-a-video-file)
- [Capturing and Previewing BGR frames from a video file](../basic/decode-video-files/#capturing-and-previewing-bgr-frames-from-a-video-file) _(OpenCV Support)_
- [Playing with any other FFmpeg pixel formats](../basic/decode-video-files/#capturing-and-previewing-bgr-frames-from-a-video-file)
- [x] **[:material-webcam: Decoding Live Feed Devices](../basic/decode-live-feed-devices/#decoding-live-feed-devices)**
diff --git a/docs/recipes/basic/transcode-live-frames-simplegraphs.md b/docs/recipes/basic/transcode-live-frames-simplegraphs.md
index 665e336..993240d 100644
--- a/docs/recipes/basic/transcode-live-frames-simplegraphs.md
+++ b/docs/recipes/basic/transcode-live-frames-simplegraphs.md
@@ -81,6 +81,8 @@ We'll discuss the transcoding of live simple filtergraphs in the following recip
In this example we will take the first 5 seconds of a video clip _(using [`trim`](https://ffmpeg.org/ffmpeg-filters.html#toc-trim) filter)_ and reverse it _(by applying [`reverse`](https://ffmpeg.org/ffmpeg-filters.html#toc-reverse) filter)_, and encode them using OpenCV Library's [`VideoWriter()`](https://docs.opencv.org/3.4/dd/d9e/classcv_1_1VideoWriter.html#ad59c61d8881ba2b2da22cff5487465b5) method in real-time.
+!!! warning "The `reverse` filter requires memory to buffer the entire clip, so applying [`trim`](https://ffmpeg.org/ffmpeg-filters.html#toc-trim) filter first is strongly recommended. Otherwise you might probably run Out of Memory."
+
!!! info "OpenCV's `VideoWriter()` class requires a valid Output filename _(e.g. output_foo.avi)_, [FourCC](https://www.fourcc.org/fourcc.php) code, framerate, and resolution as input."
!!! tip "You can use FFdecoder's [`metadata`](../../reference/ffdecoder/#deffcode.ffdecoder.FFdecoder.metadata) property object that dumps source Video's metadata information _(as JSON string)_ to retrieve source framerate and resolution."
diff --git a/mkdocs.yml b/mkdocs.yml
index 105dc7c..23fd4eb 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -61,7 +61,7 @@ theme:
icon: fontawesome/solid/lightbulb
name: Switch to light mode
font: # font
- text: Heebo
+ text: Libre Franklin
code: JetBrains Mono
icon: # icon
logo: logo
diff --git a/setup.py b/setup.py
index 07fb6e6..c2019aa 100644
--- a/setup.py
+++ b/setup.py
@@ -30,15 +30,26 @@
with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()
+ # patch internal hyperlinks
long_description = long_description.replace(
"(#", "(https://github.com/abhiTronix/deffcode#"
)
long_description = long_description.replace(
- "docs/overrides/", "(https://abhitronix.github.io/deffcode/latest/"
+ "docs/overrides/", "https://abhitronix.github.io/deffcode/latest/"
+ )
+ # patch to remove github README specific text
+ long_description = (
+ long_description.replace(
+ "![DeFFcode](docs/overrides/assets/images/deffcode-dark.png#gh-dark-mode-only)",
+ "",
+ )
+ .replace("#gh-light-mode-only", "")
+ .replace("
", "")
+ .replace("", "")
)
# patch for unicodes
- long_description = long_description.replace("➶", ">>")
- long_description = long_description.replace("©", "(c)")
+ long_description = long_description.replace("➶", ">>").replace("©", "(c)")
+
setup(
name="deffcode",
@@ -63,7 +74,7 @@
"Decoder",
"Realtime",
"Framework",
- "Cross-platform"
+ "Cross-platform",
"Video Processing",
"Computer Vision",
"Video Decoding",
diff --git a/tests/test_ffdecoder.py b/tests/test_ffdecoder.py
index d1b6ed3..66a104e 100644
--- a/tests/test_ffdecoder.py
+++ b/tests/test_ffdecoder.py
@@ -349,28 +349,28 @@ def test_FFdecoder_params(source, ffparams, result):
f_name = os.path.join(*[tempfile.gettempdir(), "temp_write", "output_foo.avi"])
try:
# initialize and formulate the decode with suitable source
- decoder = FFdecoder(source, frame_format="bgr24", **ffparams).formulate()
+ with FFdecoder(source, frame_format="bgr24", **ffparams) as decoder:
- # retrieve JSON Metadata and convert it to dict
- metadata_dict = json.loads(decoder.metadata)
+ # retrieve JSON Metadata and convert it to dict
+ metadata_dict = json.loads(decoder.metadata)
- # prepare OpenCV parameters
- FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
- FRAMERATE = metadata_dict["source_video_framerate"]
- FRAMESIZE = tuple(metadata_dict["source_video_resolution"])
+ # prepare OpenCV parameters
+ FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
+ FRAMERATE = metadata_dict["source_video_framerate"]
+ FRAMESIZE = tuple(metadata_dict["source_video_resolution"])
- # Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
- writer = cv2.VideoWriter(f_name, FOURCC, FRAMERATE, FRAMESIZE)
+ # Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
+ writer = cv2.VideoWriter(f_name, FOURCC, FRAMERATE, FRAMESIZE)
- # grab the BGR24 frame from the decoder
- for frame in decoder.generateFrame():
+ # grab the BGR24 frame from the decoder
+ for frame in decoder.generateFrame():
- # check if frame is None
- if frame is None:
- break
+ # check if frame is None
+ if frame is None:
+ break
- # writing BGR24 frame to writer
- writer.write(frame)
+ # writing BGR24 frame to writer
+ writer.write(frame)
except Exception as e:
if result:
pytest.fail(str(e))
@@ -378,7 +378,6 @@ def test_FFdecoder_params(source, ffparams, result):
pytest.xfail(str(e))
finally:
# terminate the decoder
- not (decoder is None) and decoder.terminate()
not (writer is None) and writer.release() and remove_file_safe(f_name)