diff --git a/plugins/python-codecs/package-lock.json b/plugins/python-codecs/package-lock.json index effd438936..4051e9051d 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.20", + "version": "0.1.21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@scrypted/python-codecs", - "version": "0.1.20", + "version": "0.1.21", "devDependencies": { "@scrypted/sdk": "file:../../sdk" } diff --git a/plugins/python-codecs/package.json b/plugins/python-codecs/package.json index 55ed7e6c18..5c2d3b33f1 100644 --- a/plugins/python-codecs/package.json +++ b/plugins/python-codecs/package.json @@ -1,6 +1,6 @@ { "name": "@scrypted/python-codecs", - "version": "0.1.20", + "version": "0.1.21", "description": "Python Codecs for Scrypted", "keywords": [ "scrypted", diff --git a/plugins/python-codecs/src/libav.py b/plugins/python-codecs/src/libav.py index ad4c63e320..889d8e9ead 100644 --- a/plugins/python-codecs/src/libav.py +++ b/plugins/python-codecs/src/libav.py @@ -27,6 +27,8 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option # stream.codec_context.options['-analyzeduration'] = '0' # stream.codec_context.options['-probesize'] = '500000' + gray = options and options.get('format') == 'gray' + start = 0 try: for idx, frame in enumerate(container.decode(stream)): @@ -39,7 +41,12 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option continue # print(frame) if vipsimage.pyvips: - vips = vipsimage.pyvips.Image.new_from_array(frame.to_ndarray(format='rgb24')) + if gray and frame.format.name.startswith('yuv') and frame.planes and len(frame.planes): + vips = vipsimage.new_from_memory(memoryview(frame.planes[0]), frame.width, frame.height, 1) + elif gray: + vips = vipsimage.pyvips.Image.new_from_array(frame.to_ndarray(format='gray')) + else: + vips = vipsimage.pyvips.Image.new_from_array(frame.to_ndarray(format='rgb24')) vipsImage = vipsimage.VipsImage(vips) try: mo = await vipsimage.createVipsMediaObject(vipsImage) @@ -48,7 +55,16 @@ async def generateVideoFramesLibav(mediaObject: scrypted_sdk.MediaObject, option vipsImage.vipsImage = None vips.invalidate() else: - pil = frame.to_image() + if gray and frame.format.name.startswith('yuv') and frame.planes and len(frame.planes): + pil = pilimage.new_from_memory(memoryview(frame.planes[0]), frame.width, frame.height, 1) + elif gray: + rgb = frame.to_image() + try: + pil = rgb.convert('L') + finally: + rgb.close() + else: + pil = frame.to_image() pilImage = pilimage.PILImage(pil) try: mo = await pilimage.createPILMediaObject(pilImage) diff --git a/plugins/python-codecs/src/pilimage.py b/plugins/python-codecs/src/pilimage.py index 7e76a9ce3e..512afd9cdd 100644 --- a/plugins/python-codecs/src/pilimage.py +++ b/plugins/python-codecs/src/pilimage.py @@ -21,19 +21,26 @@ async def toBuffer(self, options: scrypted_sdk.ImageOptions = None) -> bytearray if not options or not options.get('format', None): def format(): - bytesArray = io.BytesIO() - pilImage.pilImage.save(bytesArray, format='JPEG') - return bytesArray.getvalue() + return pilImage.pilImage.tobytes() return await to_thread(format) elif options['format'] == 'rgb': def format(): - rgb = pilImage.pilImage - if rgb.format == 'RGBA': - rgb = rgb.convert('RGB') - return rgb.tobytes() + rgbx = pilImage.pilImage + if rgbx.format != 'RGBA': + return rgbx.tobytes() + rgb = rgbx.convert('RGB') + try: + return rgb.tobytes() + finally: + rgb.close() return await to_thread(format) - return await to_thread(lambda: pilImage.pilImage.write_to_buffer('.' + options['format'])) + def save(): + bytesArray = io.BytesIO() + pilImage.pilImage.save(bytesArray, format=options['format']) + return bytesArray.getvalue() + + return await to_thread(lambda: save()) async def toPILImage(self, options: scrypted_sdk.ImageOptions = None): return await to_thread(lambda: toPILImage(self, options))