diff --git a/plugins/python-codecs/package-lock.json b/plugins/python-codecs/package-lock.json index 0b56477610..4b7b0a0f30 100644 --- a/plugins/python-codecs/package-lock.json +++ b/plugins/python-codecs/package-lock.json @@ -1,12 +1,12 @@ { "name": "@scrypted/python-codecs", - "version": "0.1.94", + "version": "0.1.95", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/python-codecs", - "version": "0.1.94", + "version": "0.1.95", "devDependencies": { "@scrypted/sdk": "file:../../sdk" } diff --git a/plugins/python-codecs/package.json b/plugins/python-codecs/package.json index e49c0659d2..5e75e33d95 100644 --- a/plugins/python-codecs/package.json +++ b/plugins/python-codecs/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/python-codecs", - "version": "0.1.94", + "version": "0.1.95", "description": "Python Codecs for Scrypted", "keywords": [ "scrypted", diff --git a/plugins/python-codecs/src/gstreamer.py b/plugins/python-codecs/src/gstreamer.py index c3f0c73b3e..0849fa11fd 100644 --- a/plugins/python-codecs/src/gstreamer.py +++ b/plugins/python-codecs/src/gstreamer.py @@ -1,7 +1,6 @@ -import asyncio import platform from asyncio import Future -from typing import Any +from typing import Any, AsyncGenerator from urllib.parse import urlparse import scrypted_sdk @@ -10,12 +9,8 @@ import vipsimage from generator_common import createImageMediaObject, createVideoFrame from gst_generator import Gst, createPipelineIterator -from gstreamer_postprocess import ( - GstreamerPostProcess, - OpenGLPostProcess, - VaapiPostProcess, - getBands, -) +from gstreamer_postprocess import (GstreamerPostProcess, OpenGLPostProcess, + VaapiPostProcess, getBands) from util import optional_chain @@ -317,7 +312,7 @@ async def generateVideoFramesGstreamer( h264Decoder: str = None, h265Decoder: str = None, postProcessPipeline: str = None, -) -> scrypted_sdk.VideoFrame: +) -> AsyncGenerator[scrypted_sdk.VideoFrame, Any]: ffmpegInput: scrypted_sdk.FFmpegInput = ( await scrypted_sdk.mediaManager.convertMediaObjectToJSON( mediaObject, scrypted_sdk.ScryptedMimeTypes.FFmpegInput.value diff --git a/plugins/python-codecs/src/libav.py b/plugins/python-codecs/src/libav.py index 9c24971d7b..91e335cccb 100644 --- a/plugins/python-codecs/src/libav.py +++ b/plugins/python-codecs/src/libav.py @@ -1,6 +1,6 @@ import time import scrypted_sdk -from typing import Any +from typing import Any, AsyncGenerator import vipsimage import pilimage from generator_common import createVideoFrame, createImageMediaObject @@ -20,7 +20,7 @@ async def generateVideoFramesLibav( mediaObject: scrypted_sdk.MediaObject, options: scrypted_sdk.VideoFrameGeneratorOptions = None, -) -> scrypted_sdk.VideoFrame: +) -> AsyncGenerator[scrypted_sdk.VideoFrame, Any]: ffmpegInput: scrypted_sdk.FFmpegInput = ( await scrypted_sdk.mediaManager.convertMediaObjectToJSON( mediaObject, scrypted_sdk.ScryptedMimeTypes.FFmpegInput.value diff --git a/plugins/python-codecs/src/main.py b/plugins/python-codecs/src/main.py index e28190526d..93b0d2fcd6 100644 --- a/plugins/python-codecs/src/main.py +++ b/plugins/python-codecs/src/main.py @@ -1,15 +1,16 @@ -import traceback import asyncio +import time +import traceback +from typing import Any, AsyncGenerator, List, Union + import scrypted_sdk from scrypted_sdk import Setting, SettingValue -from typing import Any, List, Union + import gstreamer import libav -import vipsimage import pilimage -import time +import vipsimage import zygote -import os Gst = None try: @@ -201,20 +202,23 @@ def multiprocess_exit(): class CodecFork: + def timeoutExit(): + print("Frame yield timed out, exiting pipeline.") + multiprocess_exit() + async def generateVideoFrames(self, iter, src: str, firstFrameOnly=False): start = time.time() loop = asyncio.get_event_loop() - def timeoutExit(): - print("Frame yield timed out, exiting pipeline.") - multiprocess_exit() - try: while True: + self.timeout.cancel() + self.timeout = loop.call_later(10, self.timeoutExit) data = await asyncio.wait_for(iter.__anext__(), timeout=10) - timeout = loop.call_later(10, timeoutExit) + self.timeout.cancel() + self.timeout = loop.call_later(10, self.timeoutExit) yield data - timeout.cancel() + if firstFrameOnly: break except Exception: @@ -231,7 +235,10 @@ async def generateVideoFramesGstreamer( h264Decoder: str, h265Decoder: str, postProcessPipeline: str, - ) -> scrypted_sdk.VideoFrame: + ) -> AsyncGenerator[scrypted_sdk.VideoFrame, Any]: + loop = asyncio.get_event_loop() + self.timeout = loop.call_later(10, self.timeoutExit) + async for data in self.generateVideoFrames( gstreamer.generateVideoFramesGstreamer( mediaObject, options, h264Decoder, h265Decoder, postProcessPipeline @@ -245,7 +252,10 @@ async def generateVideoFramesLibav( self, mediaObject: scrypted_sdk.MediaObject, options: scrypted_sdk.VideoFrameGeneratorOptions = None, - ) -> scrypted_sdk.VideoFrame: + ) -> AsyncGenerator[scrypted_sdk.VideoFrame, Any]: + loop = asyncio.get_event_loop() + self.timeout = loop.call_later(10, self.timeoutExit) + async for data in self.generateVideoFrames( libav.generateVideoFramesLibav(mediaObject, options), "libav",