Help with hiding IP camera address and displaying camera image as part of the template page url

I am building a template that displays image(s) from IP camera(s).
Every camera has different IP address from where to request its image.

I would like to hide the IP address in Sage 9 front-end and create + show the camera image path in cameras page template something like: https://mysite.com/cameras/webcam1.jpg

I would appreciate any ideas, suggestions, help how to achieve this or implement it in Roots full stack environment.

Below is the code that did the magic until now …

<?php
      function update() {
        file_put_contents(realpath(dirname(__FILE__) . "/cameras/webcam1.jpg"), file_get_contents("http://ip.to.hide.in.front.end/record/current.jpg?rand=".rand(1,999999)));
    }

    ...  some setTimeInterval stuff

    echo 'refreshed image' on template-cameras.blade.php;

This is more of a WordPress question than a Roots question, really, but you could look at programmatically importing the images into WordPress, so that the camera isn’t involved in displaying the images.

See this gist as an example:

1 Like

I would be a bit cautious about importing all the images in WordPress, especially if the camera updates the image very frequently and/or the code that imports the image is called a lot (like on page load). Unless you actually want a media library full of every image retrieved from the cameras, it could be a bit of a headache later…

It sounds like all you really is a URL mask for each camera, so you could even do this at the server level with mod_rewrite or whatever URL rewriting library is appropriate to your server.

If the camera IP addresses don’t need to be editable by normal WordPress users, you could even create individual rules for each camera in your .htaccess file (assuming you use Apache).

e.g
RewriteRule ^cameras/webcam1\.jpg$ http://1.2.3.4/record/current.jpg?t=%{TIME} [P]
RewriteRule ^cameras/webcam2\.jpg$ http://5.6.7.8/record/current.jpg?t=%{TIME} [P]

With mod_rewrite you can proxy the request ([P]) and also pass a variable for the time (%{TIME}) if you want a unique URL like in your example. See here for more details:

http://httpd.apache.org/docs/current/rewrite/flags.html#flag_p
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond

You could also make a more dynamic version that will take the camera’s number and pass it to a script, which could then be responsible for fetching and returning the image:

RewriteRule ^cameras/webcam([^/]*)\.jpg$ /fetch.php?camera=$1 [L]

Your fetch.php could contain the code you posted originally with a switch statement for each camera. You could save the file locally or simply stream it out to the user. Just make sure you set the appropriate HTTP headers for an image and also set whatever caching you want for your “image”.

PS: I didn’t actually test the above mod_rewrite rules and it’s not my strong point but hopefully it gives you a starting point.

2 Likes

I’m really really grateful for your answers, thank you! :+1:

camera image refreshes 2-4 frames per sec

hmmm, I have Nginx servers and https in staging/production, but camera ip is served over http://

should I set up an encrypted reverse proxy with nginx-includes in the server?

You’re welcome :slight_smile:

I don’t have that much experience with Nginx but if you’re doing a straight proxy, maybe you will need an encrypted reverse proxy, unless unless Nginx automatically will fetch it from HTTP and then encrypt it to send to the client via HTTPS. I really don’t know but you could always try the simplest version.

If you were to use PHP via file_get_contents(), the image would be fetched internally by the server and then if you streamed it back to the client, I think that would encrypt it if you had a secure connection already. However, it’s probably much less efficient to pass the data through PHP so I’d try the Nginx solution first.

I’ll be curious to know how you end up doing it…

1 Like

You could use something like restreamer.

1 Like

If you are using nginx you can use something like the following for proxying a specific url to a different server:

location ~ /fake/address/ {
    proxy_redirect off;
    proxy_set_header Host $host;
   
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
    proxy_pass_request_headers on;
    proxy_set_header Connection "keep-alive";
    proxy_store off;
    proxy_pass http://1.2.3.4/somepath/$is_args$args;
}

Hope that helps.

2 Likes

here is my solution with IP camera that has public http://../current.jpg image endpoint set

I created new nginx configuration template file to
trellis > nginx-includes > proxy.conf.j2

conf inside this template file will be included to mysite.com.conf file in nginx web server

proxy.conf.j2

location /webcam {
  proxy_pass http://ip.ip.ip.ip:ipip/record/current.jpg;
}

then I updated server conf just for nginx includes
ansible-playbook server.yml -e env=production --tags nginx-includes

in wordpress admin I created new page with url webcam

https://mysite.com/webcam

I have proxied url there along with the camera image there with src="" attribute …

… which I can use in front-end on mysite with help of some javascript

<img ... src="https://mysite.com/webcam">

in front-end I use JS to display static image on mysite.com front-page template and then refresh it inside the modal when modal is open and end refreshing when modal is closed

theme/resources/assets/scripts/routes/home.js

    const cameraBackground = document.getElementById("cameraBg");
    cameraBackground.src = "https://mysite.com/webcam"

    let cameraRefreshInterval

    function refreshCameraImage() {
      const cameraModalImage = document.getElementById("camera");
      cameraModalImage.src = "https://mysite.com/webcam/?rand=" + Math.random();
    }
    
    $("#cameraModal").on("show.bs.modal", function () {
        cameraRefreshInterval = setInterval(refreshCameraImage, 1000);
      }
    );

    $("#cameraModal").on("hidden.bs.modal", function() {
      clearInterval(cameraRefreshInterval);
    });

scroll down and find camera icon :slight_smile: mysite.com

2 Likes

Thanks for coming back to share your solution! :sunglasses: