koush / scrypted

Scrypted is a high performance video integration and automation platform
https://scrypted.app
Other
4.37k stars 256 forks source link

The Scrypted plugin for OpenCV fails to start, throwing an ImportError for the `Image` module from the `PIL` library. #1520

Closed cwawak closed 3 months ago

cwawak commented 5 months ago

Describe the bug The Scrypted plugin for OpenCV fails to start, throwing an ImportError for the Image module from the PIL library.

To Reproduce Steps to reproduce the behavior:

  1. Start the Scrypted server.
  2. Load the OpenCV plugin.
  3. Observe the error in the logs.

Expected behavior The OpenCV plugin should start without errors, and the Image module from PIL should be successfully imported.

Screenshots N/A

Server (please complete the following information):

Hardware Model (please complete the following information):

Client (please complete the following information, if applicable):

Additional context This issue is running under Fedora using Podman, with the following image: docker.io/koush/scrypted:v0.114.0-jammy-full

Traceback:

linux x64 #1 SMP PREEMPT_DYNAMIC Thu May  2 18:50:49 UTC 2024
server version: 0.114.0
plugin version: @scrypted/opencv 0.0.91
full
########################
7/7/2024, 12:55:07 PM
########################
python version: python3.10
interpreter: /usr/bin/python3
pip target: /server/volume/plugins/@scrypted/opencv/python3.10-Linux-x86_64-20240317
requirements.txt (up to date)
# must ensure numpy is pinned to prevent dependencies with an unpinned numpy from pulling numpy>=2.0.
numpy==1.26.4
imutils>=0.5.0
opencv-python==4.10.0.82
Pillow==10.3.0

plugin start/fork failed
Traceback (most recent call last):
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 379, in loadZip
    return await self.loadZipWrapped(packageJson, getZip, options)
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 690, in loadZipWrapped
    from main import create_scrypted_plugin  # type: ignore
  File "/server/volume/plugins/@scrypted/opencv/zip/1-e7219c81a6fa17e84dfbc7760e7a2a2a.zip/main.py", line 1, in <module>
    from opencv import OpenCVPlugin
  File "/server/volume/plugins/@scrypted/opencv/zip/1-e7219c81a6fa17e84dfbc7760e7a2a2a.zip/opencv/__init__.py", line 12, in <module>
    from PIL import Image
ImportError: cannot import name 'Image' from 'PIL' (unknown location)
koush commented 4 months ago

does delete and reinstall plugin resolve this?

cwawak commented 4 months ago

Hi @koush - I deleted the plugins directory and restarted the container and all the plugins built fine. Apologies for the erroneous bug report! I'll remember to try this next time.

Thank you!

cwawak commented 3 months ago

This identical issue has happened 3-4 times, each time working for a day or so. Each time I stop scrypted, delete the entire plugins folder, and start scrypted. Eventually there is a plugin update or something after which the error appears again.

linux x64 #1 SMP PREEMPT_DYNAMIC Sat Jul 27 15:56:15 UTC 2024
server version: 0.114.0
plugin version: @scrypted/opencv 0.0.91
full
########################
8/12/2024, 5:07:34 PM
########################
python version: python3.10
interpreter: /usr/bin/python3
pip target: /server/volume/plugins/@scrypted/opencv/python3.10-Linux-x86_64-20240317
requirements.txt (up to date)
# must ensure numpy is pinned to prevent dependencies with an unpinned numpy from pulling numpy>=2.0.
numpy==1.26.4
imutils>=0.5.0
opencv-python==4.10.0.82
Pillow==10.3.0

plugin start/fork failed
Traceback (most recent call last):
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 379, in loadZip
    return await self.loadZipWrapped(packageJson, getZip, options)
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 690, in loadZipWrapped
    from main import create_scrypted_plugin  # type: ignore
  File "/server/volume/plugins/@scrypted/opencv/zip/1-e7219c81a6fa17e84dfbc7760e7a2a2a.zip/main.py", line 1, in <module>
    from opencv import OpenCVPlugin
  File "/server/volume/plugins/@scrypted/opencv/zip/1-e7219c81a6fa17e84dfbc7760e7a2a2a.zip/opencv/__init__.py", line 12, in <module>
    from PIL import Image
ImportError: cannot import name 'Image' from 'PIL' (unknown location)
cwawak commented 3 months ago

Other failing plugins:

python codecs v0.1.96

linux x64 #1 SMP PREEMPT_DYNAMIC Sat Jul 27 15:56:15 UTC 2024
server version: 0.114.0
plugin version: @scrypted/python-codecs 0.1.96
full
########################
8/13/2024, 3:59:08 PM
########################
python version: python3.10
interpreter: /usr/bin/python3
pip target: /server/volume/plugins/@scrypted/python-codecs/python3.10-Linux-x86_64-20240317
requirements.txt (up to date)
# needed by libav to_ndarray
numpy>=1.16.2

av>=10.0.0

# in case pyvips fails to load, use a pillow fallback.
# pillow for anything not intel linux, pillow-simd is available on x64 linux
Pillow>=5.4.1; sys_platform != 'linux' or platform_machine != 'x86_64'
pillow-simd; sys_platform == 'linux' and platform_machine == 'x86_64'

plugin start/fork failed
Traceback (most recent call last):
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 379, in loadZip
    return await self.loadZipWrapped(packageJson, getZip, options)
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 690, in loadZipWrapped
    from main import create_scrypted_plugin  # type: ignore
  File "/server/volume/plugins/@scrypted/python-codecs/zip/1-0635e5c25453427948dd32cb00d631de.zip/main.py", line 10, in <module>
    import gstreamer
  File "/server/volume/plugins/@scrypted/python-codecs/zip/1-0635e5c25453427948dd32cb00d631de.zip/gstreamer.py", line 8, in <module>
    import pilimage
  File "/server/volume/plugins/@scrypted/python-codecs/zip/1-0635e5c25453427948dd32cb00d631de.zip/pilimage.py", line 13, in <module>
    class PILImage(scrypted_sdk.Image):
  File "/server/volume/plugins/@scrypted/python-codecs/zip/1-0635e5c25453427948dd32cb00d631de.zip/pilimage.py", line 14, in PILImage
    def __init__(self, pilImage: Image.Image) -> None:
NameError: name 'Image' is not defined

openvino v0.1.109

linux x64 #1 SMP PREEMPT_DYNAMIC Sat Jul 27 15:56:15 UTC 2024
server version: 0.114.0
plugin version: @scrypted/openvino 0.1.109
full
########################
8/12/2024, 5:07:34 PM
########################
python version: python3.10
interpreter: /usr/bin/python3
pip target: /server/volume/plugins/@scrypted/openvino/python3.10-Linux-x86_64-20240317
requirements.txt (up to date)
# must ensure numpy is pinned to prevent dependencies with an unpinned numpy from pulling numpy>=2.0.
numpy==1.26.4
openvino==2024.2.0
Pillow==10.3.0
opencv-python==4.10.0.84

plugin start/fork failed
Traceback (most recent call last):
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 379, in loadZip
    return await self.loadZipWrapped(packageJson, getZip, options)
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 690, in loadZipWrapped
    from main import create_scrypted_plugin  # type: ignore
  File "/server/volume/plugins/@scrypted/openvino/zip/1-b03f191500062a575dc2f8742476e673.zip/main.py", line 1, in <module>
    from ov import OpenVINOPlugin
  File "/server/volume/plugins/@scrypted/openvino/zip/1-b03f191500062a575dc2f8742476e673.zip/ov/__init__.py", line 11, in <module>
    import openvino.runtime as ov
ModuleNotFoundError: No module named 'openvino.runtime'

tensorflow lite v0.1.65

linux x64 #1 SMP PREEMPT_DYNAMIC Sat Jul 27 15:56:15 UTC 2024
server version: 0.114.0
plugin version: @scrypted/tensorflow-lite 0.1.65
full
########################
8/13/2024, 4:00:09 PM
########################
python version: python3.9
interpreter: /usr/bin/python3.9
pip target: /server/volume/plugins/@scrypted/tensorflow-lite/python3.9-Linux-x86_64-20240317
requirements.txt (up to date)
--extra-index-url https://google-coral.github.io/py-repo/
# must ensure numpy is pinned to prevent dependencies with an unpinned numpy from pulling numpy>=2.0.
numpy==1.26.4
pycoral~=2.0
tflite-runtime==2.5.0.post1
Pillow==10.3.0

plugin start/fork failed
Traceback (most recent call last):
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 379, in loadZip
    return await self.loadZipWrapped(packageJson, getZip, options)
  File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 690, in loadZipWrapped
    from main import create_scrypted_plugin  # type: ignore
  File "<frozen zipimport>", line 259, in load_module
  File "/server/volume/plugins/@scrypted/tensorflow-lite/zip/1-9e41a00b2401b34031a773d8ca628b6b.zip/main.py", line 1, in <module>
    from tflite import TensorFlowLitePlugin
  File "<frozen zipimport>", line 259, in load_module
  File "/server/volume/plugins/@scrypted/tensorflow-lite/zip/1-9e41a00b2401b34031a773d8ca628b6b.zip/tflite/__init__.py", line 6, in <module>
    from PIL import Image
ImportError: cannot import name 'Image' from 'PIL' (unknown location)
koush commented 3 months ago

are you using nvr? why is TFLite installed?

cwawak commented 3 months ago

I am an NVR user. I don't know why TFLite is installed. I removed it.

koush commented 3 months ago

Understood, tflite should be installed if you have a coral. Which it sounds like you do not have.

As an nvr user, you can also delete python codecs and opencv (not to be confused with openvino). You do not need any of these plugins.

After you do that, recreate the container with docker compose down && docker compose up

let me know if the issue persists.

cwawak commented 3 months ago

I am starting the container like so:

/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --sdnotify=conmon -d --replace -it --network network1234 --ip 1.2.3.4 --name scrypted -v /var/containervolumes/scrypted/volume:/server/volume:z -v /volume3/scratch/video:/video -v /scryptedfast:/scryptedfast:z docker.io/koush/scrypted:v0.115.5-jammy-full

So, the first startup after deleting the plugins folder all plugins work fine. Upon subsequent restarts, the OpenCV plugin fails:

Aug 14 14:03:24 scrypted[1595571]: Traceback (most recent call last):
Aug 14 14:03:24 scrypted[1595571]:   File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 489, in loadZip
Aug 14 14:03:24 scrypted[1595571]:     return await self.loadZipWrapped(packageJson, getZip, options)
Aug 14 14:03:24 scrypted[1595571]:   File "/server/node_modules/@scrypted/server/python/plugin_remote.py", line 893, in loadZipWrapped
Aug 14 14:03:24 scrypted[1595571]:     from main import create_scrypted_plugin  # type: ignore
Aug 14 14:03:24 scrypted[1595571]:   File "/server/volume/plugins/@scrypted/openvino/zip/1-b03f191500062a575dc2f8742476e673.zip/main.py", line 1, in <module>
Aug 14 14:03:24 scrypted[1595571]:     from ov import OpenVINOPlugin
Aug 14 14:03:24 scrypted[1595571]:   File "/server/volume/plugins/@scrypted/openvino/zip/1-b03f191500062a575dc2f8742476e673.zip/ov/__init__.py", line 11, in <module>
Aug 14 14:03:24 scrypted[1595571]:     import openvino.runtime as ov
Aug 14 14:03:24 scrypted[1595571]: ModuleNotFoundError: No module named 'openvino.runtime'

As a workaround, I'll just rm the plugins directory on restarts of the container which increases load on downloading the modules, but at least avoids issues with object detection not working.

koush commented 3 months ago

What is the :z doing in your volume mount there?

No one else has reported the issue, but I am also not aware of anyone else using podman, so now I'm thinking it's something related to the host environment.

cwawak commented 3 months ago

it certainly can be related to the host environment, though I have no idea how that might be!

:z tells podman to relabel the directory with a shared SELinux context that allows the container to access it, even if the container's SELinux policy would otherwise prevent it from doing so. :Z would give a "private" context specific to the container, and I could see where that might cause problems, but I'm not using :Z.

specifically the system_u:object_r:container_file_t:s0 context. i run multiple applications on this host, and use SElinux to ensure proper isolation between the host OS and the container.

it could very well be a podman thing, but I don't see any SElinux AVCs or denials that would indicate an SElinux or permissions issue. additionally, this only seemed to start happening maybe ~6 months ago, more or less. I am running wyze-bridge, step, home-assistant, and a few other applications on this particular host using :z for volumes.

I'm happy to do the following based on your ideas:

koush commented 3 months ago

my hunch is that there may be some permission issue when downloading new binaries after the container has started. openvino, tflite, and I think PIL all have native code in them possibly.

cwawak commented 3 months ago

I disabled selinux on the volume mount and it started up fine the first time, but on restart I see the same behavior and error. I have log files from the initial run and then the run where it failed, I can send them over on Discord if you're interested. If not, I think I'm OK with just clearing out the plugins file on restart until I decide whether I want to shift away from podman (used to work at Red Hat, no longer have a religious reason to use podman) or what.

koush commented 3 months ago

can you try the beta tag