WIP Multi Cam
#1
This is a thread to discuss the Multi Cam addon originally posted at http://forum.kodi.tv/showthread.php?tid=...pid1854332
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#2
Hi Leopold

as wrot on github. Your addon has an counter for the pictures you are storing in the userdata addon folder. It would be good to delete the pictures from time to time. If you have running the the addon some time the this uses a lot of space there.

Bye Shigoru
Reply
#3
Not working for me, I filled out the urls and tested them in the browers, I can see the jpg files being downloaded to the ~/.kodi/userdata/addon_data/script.multi.cam folder, also see this in the kodi.log

16:42:09 T:140451956889344 NOTICE: -->Python Interpreter Initialized<--
16:43:09 T:140451956889344 ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'socket.timeout'>
Error Contents: timed out
Traceback (most recent call last):
File "/storage/.kodi/addons/script.multi.cam/default.py", line 78, in <module>
with CamView() as viewer:
File "/storage/.kodi/addons/script.multi.cam/default.py", line 45, in __init__
urllib.urlretrieve(url, image_file)
File "/home/stephan/projects/openelec-5.0/build.OpenELEC-Generic.x86_64-5.0.2/Python-2.7.3/.install_pkg/usr/lib/python2.7/urllib.py", line 93, in urlretrieve
File "/home/stephan/projects/openelec-5.0/build.OpenELEC-Generic.x86_64-5.0.2/Python-2.7.3/.install_pkg/usr/lib/python2.7/urllib.py", line 267, in retrieve
File "/home/stephan/projects/openelec-5.0/build.OpenELEC-Generic.x86_64-5.0.2/Python-2.7.3/.install_pkg/usr/lib/python2.7/socket.py", line 379, in read
timeout: timed out
-->End of Python script error report<--
Reply
#4
Hi Leopold
is it possible for you to make some iprovements to your script? It would be great if you could spend some time for this.
Bye Shigoru
Reply
#5
same here ... (I secretly want a 6-cam version now) ... willing to pay for whatever amount of beers necessary for this Big Grin

on a side note, I find that there is a 5 to 10 second lag between the actual image on the screen and what is happening in front of the camera. Is it really optimal to capture the image and then save to a file and then read it ? is it possible to simply throw whatever is "seen" via the URL directly on screen ? bypassing the read/write cycle on the sdcard completely ? can the image be saved in memory or something ? (this might sound stupid so please correct me) !

I've been running this addon non-stop for many months now and overall its been running great (I have to reboot sometimes because it jams for unknown reasons, specially when there is a lot of movement in front of one or many cameras) but its pretty stable.
Reply
#6
(2015-02-18, 14:14)Shigoru Wrote: Hi Leopold

as wrot on github. Your addon has an counter for the pictures you are storing in the userdata addon folder. It would be good to delete the pictures from time to time. If you have running the the addon some time the this uses a lot of space there.

Bye Shigoru

I fixed this as mentioned in the old thread :

insert the following after xbmc.sleep(500)

Code:
for f in glob.glob(os.path.join(data_path, "*.jpg")):
                    os.remove(f)

it seems to be doing the trick, not too sure if this is the best way to do it... but it works well for me
Reply
#7
Hi Extraze

here is what you are searching for - 6 cam Version

https://github.com/Shigoru/script.securitycams

The beers should go to 4lb3rtO who did all the work on the script.

Just change the coordinates in the default.py to

coords = (
(12, 360, 205, 160),
(222, 360, 205, 160),
(432, 360, 205, 160),
(642, 360, 205, 160),
(852, 360, 205, 160),
(1062, 360, 205, 160),
)

if you would like to get it in fullscreen mode.

The script is flickering much at the moment but the refresh rate is very high now. I would decrease the sleep time in the script from 50 to 800ms which works much better for me.

Regards Shigoru
Reply
#8
(2015-03-09, 21:18)Shigoru Wrote: Hi Extraze

here is what you are searching for - 6 cam Version

https://github.com/Shigoru/script.securitycams

The beers should go to 4lb3rtO who did all the work on the script.

Just change the coordinates in the default.py to

coords = (
(12, 360, 205, 160),
(222, 360, 205, 160),
(432, 360, 205, 160),
(642, 360, 205, 160),
(852, 360, 205, 160),
(1062, 360, 205, 160),
)

if you would like to get it in fullscreen mode.

The script is flickering much at the moment but the refresh rate is very high now. I would decrease the sleep time in the script from 50 to 800ms which works much better for me.

Regards Shigoru

Very cool !! thanks, I will give this a try tonight !
Reply
#9
Sorry
i gave you the wrong coordinates for fullscreen

coords = (
(0, 0, 426, 360),
(426, 0, 426, 360),
(852, 0, 426, 360),
(0, 360, 426, 360),
(426, 360, 426, 360),
(852, 360, 426, 360),
)

Regards Shigoru
Reply
#10
I was troubleshooting Leopolds version last night and I found one issue.

if a camera is lagging for whatever reason, the entire program waits for that camera's feed, and after X amount of seconds (maybe a minute or two) the program freezes (this probably explains Shigoru's flickering at low refresh rates too) ... so if the camera doesn't respond, all the others don't get refreshed either, and after some time the program just stops its operation and everything stays static until you close the program or reboot the pi.

is there a way for every camera to be updated independently instead one following the other ?, this would prevent 1 single point of failure from affecting everything else.
Reply
#11
(2015-03-09, 20:46)Extraze Wrote: on a side note, I find that there is a 5 to 10 second lag between the actual image on the screen and what is happening in front of the camera. Is it really optimal to capture the image and then save to a file and then read it ? is it possible to simply throw whatever is "seen" via the URL directly on screen ? bypassing the read/write cycle on the sdcard completely ? can the image be saved in memory or something ? (this might sound stupid so please correct me) !
Unfortunately that's not possible currently as the image must be a file on disk. If you are running in Linux you could create a ramdisk and set the script to use that.

Part of the delay may be due to the network and/or the camera itself so it may not be possible to be completely "real time".

(2015-03-10, 16:23)Extraze Wrote: if a camera is lagging for whatever reason, the entire program waits for that camera's feed, and after X amount of seconds (maybe a minute or two) the program freezes (this probably explains Shigoru's flickering at low refresh rates too) ... so if the camera doesn't respond, all the others don't get refreshed either, and after some time the program just stops its operation and everything stays static until you close the program or reboot the pi.

is there a way for every camera to be updated independently instead one following the other ?, this would prevent 1 single point of failure from affecting everything else.
Yes the version I initially provided was a very "quick and dirty" proof of concept. Ideally each image should be updated in a separate thread.

The flickering is a Kodi issue but the effect can be mitigated by having two image controls superimposed, both showing the same image.

If I get some time I'll see what I can do.
Leopold's Repository: Home of LibreELEC Dev Updater ...
Reply
#12
thank you for taking the time to answer our questions, it is very appreciated !
Reply
#13
(2015-03-09, 21:18)Shigoru Wrote: Hi Extraze

here is what you are searching for - 6 cam Version

https://github.com/Shigoru/script.securitycams

The beers should go to 4lb3rtO who did all the work on the script.

Just change the coordinates in the default.py to

coords = (
(12, 360, 205, 160),
(222, 360, 205, 160),
(432, 360, 205, 160),
(642, 360, 205, 160),
(852, 360, 205, 160),
(1062, 360, 205, 160),
)

if you would like to get it in fullscreen mode.

The script is flickering much at the moment but the refresh rate is very high now. I would decrease the sleep time in the script from 50 to 800ms which works much better for me.

Regards Shigoru

I played around with the script and indeed it works well, (except for the flickering... I was not getting any of this with Leopolds version, so I think we need a hybrid of both Wink ... )

I made some changes if anyone wants it to look cleaner (I added a couple of pixels for borders between each camera and put a black background so you only see black when the images flicker (and gives you the black borders)) ...

you need to add a file called "black.png" (which is a single black pixel) in /resources/media for this to work.
you can download one here : http://upload.wikimedia.org/wikipedia/en..._Pixel.png

Code:
import xbmc
import xbmcgui
import xbmcvfs
import xbmcaddon
import os.path
from urllib import urlretrieve
from PIL import Image
from threading import Thread


addon   = xbmcaddon.Addon()
addonid = addon.getAddonInfo('id')
addonname = addon.getAddonInfo('name')
black = os.path.join(addon.getAddonInfo('path'), 'resources', 'media', 'black.png')

ACTION_PREVIOUS_MENU = 10
ACTION_STOP = 13
ACTION_NAV_BACK = 92
ACTION_BACKSPACE = 110



class CamWindow(xbmcgui.WindowDialog):
    def __init__(self):
        self.addControl(xbmcgui.ControlImage(0, 0, 1280, 720, black))
        path = xbmc.translatePath('special://profile/addon_data/%s' %addonid )
        loader = xbmc.translatePath('special://home/addons/%s/resources/loader.gif' %addonid )
        

        if not xbmcvfs.exists(path):
            xbmcvfs.mkdir(path)


        urls = [
        addon.getSetting('URL1'),
        addon.getSetting('URL2'),
        addon.getSetting('URL3'),
        addon.getSetting('URL4'),
        addon.getSetting('URL5'),
        addon.getSetting('URL6')
        ]


        files = [
        os.path.join(path, '1.0.jpg'),
        os.path.join(path, '2.0.jpg'),
        os.path.join(path, '3.0.jpg'),
        os.path.join(path, '4.0.jpg'),
        os.path.join(path, '5.0.jpg'),
        os.path.join(path, '6.0.jpg')
        ]


            coords = (
            (0, 0, 425, 359),
            (428, 0, 424, 359),
            (855, 0, 425, 359),
            (0, 362, 425, 359),
            (428, 362, 424, 359),
            (855, 362, 425, 359),
        )


        imgs = []
        for c, f in zip(coords, files):
            # aspectRatio: integer - (values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars)
            img = xbmcgui.ControlImage(*c, filename=loader, aspectRatio = 0)
            self.addControl(img)            
            imgs.append(img)
        

        cams = [list(l) for l in zip(urls, files, imgs)]


        self.show()        
        self.isRunning = True


        for i, c in enumerate(cams):
            t = Thread(target=self.getImages, args=(i, c, path))
            t.start()


        while (not xbmc.abortRequested) and (self.isRunning):      
            xbmc.sleep(2000)  


        for i in xbmcvfs.listdir(path)[1]:
            if i <> "settings.xml":
                xbmcvfs.delete(os.path.join(path, i))



    def getImages(self, i, c, path):
        x=0
        while (not xbmc.abortRequested) and (self.isRunning):
            try:
                x+=1
                c[1] = os.path.join(path, '%d.%d.jpg') %(i, x)
                urlretrieve(c[0], c[1])
                #self.resizeImg(c[1])
                c[2].setImage(c[1], useCache=False)
                xbmcvfs.delete(os.path.join(path, '%d.%d.jpg') %(i, x-1))
                xbmc.sleep(2200)
            except Exception, e:
                xbmc.log(str(e))
                #error = xbmc.translatePath('special://home/addons/%s/resources/error.png' %addonid )
                #c[2].setImage(error, useCache=False)


    def onAction(self, action):
        if action in (ACTION_PREVIOUS_MENU, ACTION_STOP, ACTION_NAV_BACK, ACTION_BACKSPACE):
            self.isRunning = False
            self.close()



    #def resizeImg(self, IMAGEFILE):
    #    if xbmcvfs.exists(IMAGEFILE):
    #        img = Image.open(IMAGEFILE)
    #        img = img.resize((1280, 720))
    #        img.save(IMAGEFILE)

            

CW = CamWindow()
del CW

lines added / modified :

line 14 (new line):
Code:
black = os.path.join(__addon__.getAddonInfo('path'), 'resources', 'media', 'black.png')

line25 (existing):
Code:
self.addControl(xbmcgui.ControlImage(0, 0, 1280, 720, black))

lines 54 to 61 (existing):
Code:
coords = (
            (0, 0, 425, 359),
            (428, 0, 424, 359),
            (855, 0, 425, 359),
            (0, 362, 425, 359),
            (428, 362, 424, 359),
            (855, 362, 425, 359),
        )
Reply
#14
@Leopold

thanks for the reply about the flickering. We could fix this now with the 2 images. GREAT
We also have the 6 cams running each in a seperated thread so that the refresh rate is very high now!
4lb3rtO also added a way if one of the cams do not work any more the last image is shown in red.

So now everthing is running fine.

@ Extraze
i see you can script python - so you are welcome to improve the script.

The next level would be to add a more dynamic way for the settings of the cams.

- 1. So we would like to add a setting for the amount of cams
- 2. Preset for size and position depending of the amount of cams dynamic
- 3. Size and position changeable

https://github.com/Shigoru/script.securitycams

Confused
Reply
#15
I wouldn't say I can script python, I used to code back in college so I can get the logic and add some *easy* bits and pieces...

the setting for the amount of cam's shouldn't be a big thing, if you leave out some blank URL's in the settings the program can know and adjust the amount of cams to display (2-4-6)... if you have un-even numbers it could show an XBMC/KODI image in the blank spot.

the position of the cams can already be changed by swapping the URL's around in the settings.

i'll play around with it... no promises Wink
Reply

Logout Mark Read Team Forum Stats Members Help
Multi Cam1