deffcode
Advanced tools
| Metadata-Version: 2.1 | ||
| Name: deffcode | ||
| Version: 0.2.0 | ||
| Summary: High-performance Real-time Video frames Generator for generating blazingly fast video frames in python. | ||
| Version: 0.2.1 | ||
| Summary: High-performance Real-time FFmpeg based Video-Decoder in python. | ||
| Home-page: https://abhitronix.github.io/deffcode | ||
@@ -14,4 +14,3 @@ Author: Abhishek Thakur | ||
| Project-URL: Changelog, https://abhitronix.github.io/deffcode/latest/changelog/ | ||
| Keywords: FFmpeg,Video Processing,Computer Vision | ||
| Platform: UNKNOWN | ||
| Keywords: FFmpeg,Decoder,Video Processing,Computer Vision,Video Decoding | ||
| Classifier: Development Status :: 5 - Production/Stable | ||
@@ -182,4 +181,4 @@ Classifier: Operating System :: POSIX | ||
| - [x] Automate stuff with Continuous Integration. | ||
| - [x] Add Devices and Screen Capture support. | ||
| - [ ] Add Multiple Source Inputs support. | ||
| - [ ] Add Devices and Screen Capture support. | ||
| - [ ] Resolve High CPU usage issue with WriteGear API. | ||
@@ -272,3 +271,1 @@ - [ ] Add more parameters to Sourcer API's metadata. | ||
| [kofi]: https://ko-fi.com/W7W8WTYO | ||
+30
-17
@@ -47,3 +47,9 @@ """ | ||
| def __init__( | ||
| self, source, frame_format=None, custom_ffmpeg="", verbose=False, **extraparams | ||
| self, | ||
| source, | ||
| source_demuxer=None, | ||
| frame_format=None, | ||
| custom_ffmpeg="", | ||
| verbose=False, | ||
| **extraparams | ||
| ): | ||
@@ -78,5 +84,2 @@ """ | ||
| # handle valid FFmpeg assets location | ||
| self.__ffmpeg = "" | ||
| # handle exclusive metadata | ||
@@ -106,3 +109,3 @@ self.__ff_pixfmt_metadata = None # metadata | ||
| str(k).strip(): str(v).strip() | ||
| if not isinstance(v, (dict, list, int, float)) | ||
| if not (v is None) and not isinstance(v, (dict, list, int, float)) | ||
| else v | ||
@@ -138,4 +141,5 @@ for k, v in extraparams.items() | ||
| source=source, | ||
| source_demuxer=source_demuxer, | ||
| verbose=verbose, | ||
| ffmpeg_path=self.__ffmpeg, | ||
| custom_ffmpeg=custom_ffmpeg if isinstance(custom_ffmpeg, str) else "", | ||
| **sourcer_params | ||
@@ -147,3 +151,3 @@ ) | ||
| # get valid ffmpeg path | ||
| # handle valid FFmpeg assets location | ||
| self.__ffmpeg = self.__source_metadata["ffmpeg_binary_path"] | ||
@@ -190,11 +194,16 @@ | ||
| self.__inputframerate = self.__extra_params.pop("-framerate", 0.0) | ||
| if ( | ||
| isinstance(self.__inputframerate, (float, int)) | ||
| and self.__inputframerate > 0.0 | ||
| ): | ||
| # must be float | ||
| self.__inputframerate = float(self.__inputframerate) | ||
| if isinstance(self.__inputframerate, (float, int)): | ||
| self.__inputframerate = ( | ||
| float(self.__inputframerate) if self.__inputframerate > 0 else 0.0 | ||
| ) | ||
| elif self.__inputframerate is None: | ||
| # special case for discarding framerate value | ||
| pass | ||
| else: | ||
| # reset improper values | ||
| self.__inputframerate = 0.0 | ||
| # warn if wrong type | ||
| logger.warning( | ||
| "Discarding `-framerate` value of wrong type `{}`!".format( | ||
| type(self.__inputframerate) | ||
| ) | ||
| ) | ||
@@ -542,4 +551,8 @@ # FFmpeg parameter `-s` is unsupported | ||
| + self.__ffmpeg_postfixes | ||
| + ["-i"] | ||
| + [self.__source_metadata["source"]] | ||
| + ( | ||
| ["-f", self.__source_metadata["source_demuxer"]] | ||
| if ("source_demuxer" in self.__source_metadata.keys()) | ||
| else [] | ||
| ) | ||
| + ["-i", self.__source_metadata["source"]] | ||
| + output_parameters | ||
@@ -546,0 +559,0 @@ + ["-f", "rawvideo", "-"] |
@@ -350,3 +350,3 @@ """ | ||
| # return output findings | ||
| return [o.strip() for o in outputs] | ||
| return [o.strip() if not ("," in o) else o.split(",")[-1].strip() for o in outputs] | ||
@@ -478,6 +478,4 @@ | ||
| sp._cleanup = lambda: None | ||
| # handle additional params | ||
| retrieve_stderr = kwargs.pop("force_retrieve_stderr", False) | ||
| # execute command in subprocess | ||
@@ -490,5 +488,5 @@ process = sp.Popen( | ||
| ) | ||
| # communicate and poll process | ||
| output, stderr = process.communicate() | ||
| retcode = process.poll() | ||
| # handle return code | ||
@@ -502,3 +500,7 @@ if retcode and not (retrieve_stderr): | ||
| raise error | ||
| # raise error if no output | ||
| bool(output) or bool(stderr) or logger.error( | ||
| "FFmpeg Pipline failed to exact any metadata!" | ||
| ) | ||
| # return output otherwise | ||
| return output if not (retrieve_stderr) else stderr |
+70
-32
@@ -22,3 +22,3 @@ """ | ||
| # import required libraries | ||
| import re, logging, os | ||
| import re, logging, os, platform | ||
| import numpy as np | ||
@@ -30,2 +30,3 @@ | ||
| check_sp_output, | ||
| get_supported_demuxers, | ||
| is_valid_url, | ||
@@ -46,3 +47,10 @@ is_valid_image_seq, | ||
| def __init__(self, source, custom_ffmpeg="", verbose=False, **sourcer_params): | ||
| def __init__( | ||
| self, | ||
| source, | ||
| source_demuxer=None, | ||
| custom_ffmpeg="", | ||
| verbose=False, | ||
| **sourcer_params | ||
| ): | ||
| """ | ||
@@ -107,5 +115,8 @@ This constructor method initializes the object state and attributes of the Sourcer. | ||
| self.__source = source # handles source stream | ||
| self.__source_extension = os.path.splitext(source)[ | ||
| -1 | ||
| ] # handles source stream extension | ||
| # handles source demuxer | ||
| self.__source_demuxer = ( | ||
| source_demuxer.strip().lower() if isinstance(source_demuxer, str) else None | ||
| ) | ||
| # handles source stream extension | ||
| self.__source_extension = os.path.splitext(source)[-1] | ||
| self.__default_video_resolution = "" # handle stream resolution | ||
@@ -144,3 +155,9 @@ self.__default_video_framerate = "" # handle stream framerate | ||
| # validate source and extract metadata | ||
| self.__ffsp_output = self.__validate_source(self.__source) | ||
| self.__ffsp_output = self.__validate_source( | ||
| self.__source, | ||
| source_demuxer=self.__source_demuxer, | ||
| forced_validate=( | ||
| self.__forcevalidatesource if self.__source_demuxer is None else True | ||
| ), | ||
| ) | ||
| # parse resolution and framerate | ||
@@ -217,39 +234,57 @@ video_rfparams = self.__extract_resolution_framerate( | ||
| "source": self.__source, | ||
| "source_extension": self.__source_extension, | ||
| "source_video_resolution": self.__default_video_resolution, | ||
| "source_video_framerate": self.__default_video_framerate, | ||
| "source_video_pixfmt": self.__default_video_pixfmt, | ||
| "source_video_decoder": self.__default_video_decoder, | ||
| "source_duration_sec": self.__default_source_duration, | ||
| "approx_video_nframes": int(self.__approx_video_nframes) | ||
| if self.__approx_video_nframes | ||
| else None, | ||
| "source_video_bitrate": self.__default_video_bitrate, | ||
| "source_audio_bitrate": self.__default_audio_bitrate, | ||
| "source_audio_samplerate": self.__default_audio_samplerate, | ||
| "source_has_video": self.__contains_video, | ||
| "source_has_audio": self.__contains_audio, | ||
| "source_has_image_sequence": self.__contains_images, | ||
| } | ||
| metadata.update( | ||
| {"source_extension": self.__source_extension} | ||
| if self.__source_demuxer is None | ||
| else {"source_demuxer": self.__source_demuxer} | ||
| ) | ||
| metadata.update( | ||
| { | ||
| "source_video_resolution": self.__default_video_resolution, | ||
| "source_video_framerate": self.__default_video_framerate, | ||
| "source_video_pixfmt": self.__default_video_pixfmt, | ||
| "source_video_decoder": self.__default_video_decoder, | ||
| "source_duration_sec": self.__default_source_duration, | ||
| "approx_video_nframes": ( | ||
| int(self.__approx_video_nframes) | ||
| if self.__approx_video_nframes | ||
| else None | ||
| ), | ||
| "source_video_bitrate": self.__default_video_bitrate, | ||
| "source_audio_bitrate": self.__default_audio_bitrate, | ||
| "source_audio_samplerate": self.__default_audio_samplerate, | ||
| "source_has_video": self.__contains_video, | ||
| "source_has_audio": self.__contains_audio, | ||
| "source_has_image_sequence": self.__contains_images, | ||
| } | ||
| ) | ||
| return metadata | ||
| def __validate_source(self, source): | ||
| def __validate_source(self, source, source_demuxer=None, forced_validate=False): | ||
| """ | ||
| Internal method for validating source and extract its FFmpeg metadata. | ||
| """ | ||
| if source is None or not source or not isinstance(source, str): | ||
| raise ValueError("Input source is empty!") | ||
| # assert if valid source | ||
| assert source and isinstance(source, str), "Input source is empty!" | ||
| # assert if valid source demuxer | ||
| assert source_demuxer is None or source_demuxer in get_supported_demuxers( | ||
| self.__ffmpeg | ||
| ), "Installed FFmpeg failed to recognise `{}` demuxer. Check ``source_demuxer`` parameter value again!".format( | ||
| source_demuxer | ||
| ) | ||
| # Differentiate input | ||
| if os.path.isfile(source): | ||
| self.__video_source = os.path.abspath(source) | ||
| if forced_validate: | ||
| source_demuxer is None and logger.critical( | ||
| "Forcefully passing validation test for given source!" | ||
| ) | ||
| self.__source = source | ||
| elif os.path.isfile(source): | ||
| self.__source = os.path.abspath(source) | ||
| elif is_valid_image_seq( | ||
| self.__ffmpeg, source=source, verbose=self.__verbose_logs | ||
| ): | ||
| self.__video_source = source | ||
| self.__source = source | ||
| self.__contains_images = True | ||
| elif is_valid_url(self.__ffmpeg, url=source, verbose=self.__verbose_logs): | ||
| self.__video_source = source | ||
| elif self.__forcevalidatesource: | ||
| logger.critical("Forcefully passing validation test for given source!") | ||
| self.__video_source = source | ||
| self.__source = source | ||
| else: | ||
@@ -261,3 +296,6 @@ logger.error("`source` value is unusable or unsupported!") | ||
| metadata = check_sp_output( | ||
| [self.__ffmpeg, "-hide_banner", "-i", source], force_retrieve_stderr=True | ||
| [self.__ffmpeg, "-hide_banner"] | ||
| + (["-f", source_demuxer] if source_demuxer else []) | ||
| + ["-i", source], | ||
| force_retrieve_stderr=True, | ||
| ) | ||
@@ -264,0 +302,0 @@ # filter and return |
@@ -1,1 +0,1 @@ | ||
| __version__ = "0.2.0" | ||
| __version__ = "0.2.1" |
+4
-7
| Metadata-Version: 2.1 | ||
| Name: deffcode | ||
| Version: 0.2.0 | ||
| Summary: High-performance Real-time Video frames Generator for generating blazingly fast video frames in python. | ||
| Version: 0.2.1 | ||
| Summary: High-performance Real-time FFmpeg based Video-Decoder in python. | ||
| Home-page: https://abhitronix.github.io/deffcode | ||
@@ -14,4 +14,3 @@ Author: Abhishek Thakur | ||
| Project-URL: Changelog, https://abhitronix.github.io/deffcode/latest/changelog/ | ||
| Keywords: FFmpeg,Video Processing,Computer Vision | ||
| Platform: UNKNOWN | ||
| Keywords: FFmpeg,Decoder,Video Processing,Computer Vision,Video Decoding | ||
| Classifier: Development Status :: 5 - Production/Stable | ||
@@ -182,4 +181,4 @@ Classifier: Operating System :: POSIX | ||
| - [x] Automate stuff with Continuous Integration. | ||
| - [x] Add Devices and Screen Capture support. | ||
| - [ ] Add Multiple Source Inputs support. | ||
| - [ ] Add Devices and Screen Capture support. | ||
| - [ ] Resolve High CPU usage issue with WriteGear API. | ||
@@ -272,3 +271,1 @@ - [ ] Add more parameters to Sourcer API's metadata. | ||
| [kofi]: https://ko-fi.com/W7W8WTYO | ||
+1
-1
@@ -147,4 +147,4 @@ <!-- | ||
| - [x] Automate stuff with Continuous Integration. | ||
| - [x] Add Devices and Screen Capture support. | ||
| - [ ] Add Multiple Source Inputs support. | ||
| - [ ] Add Devices and Screen Capture support. | ||
| - [ ] Resolve High CPU usage issue with WriteGear API. | ||
@@ -151,0 +151,0 @@ - [ ] Add more parameters to Sourcer API's metadata. |
+3
-1
@@ -44,3 +44,3 @@ """ | ||
| version=pkg_version["__version__"], | ||
| description="High-performance Real-time Video frames Generator for generating blazingly fast video frames in python.", | ||
| description="High-performance Real-time FFmpeg based Video-Decoder in python.", | ||
| license="Apache License 2.0", | ||
@@ -61,4 +61,6 @@ author="Abhishek Thakur", | ||
| "FFmpeg", | ||
| "Decoder", | ||
| "Video Processing", | ||
| "Computer Vision", | ||
| "Video Decoding", | ||
| ], | ||
@@ -65,0 +67,0 @@ classifiers=[ |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
123025
1.44%1604
3.89%