0

I am trying to incorporate the rendering of H264 IP cameras/Video streams onto a webpage.

I have seen tutorials that use things like XSockets and render a webcam's footage onto a Video element or onto a canvas and would like to replicate this but using the byte[] received from the camera. Is it possible to use a custom stream instead of a local device?

I have no issue rendering a still image(i.e. single frame) onto the webpage but would instead like to be able to display the images in real time(or when we receive them from storage) instead of having to refresh the page etc. to get the next frame.

I currently do this by passing a single image as a base64 image and render using the img tag. How can I go about doing this? Is this possible using XSockets or SignalR etc.

I am using C#, .Net4.5 and Asp.Net MVC5

const_ref
  • 4,016
  • 3
  • 23
  • 38

1 Answers1

1

You can do this with both XSockets and SignalR, but there will be different approaches.

I have been sending images from a Raspberry PI to a webpage with XSockets. I snapped the image when the motion sensor (on the PI) was triggered.

You will probably get better performance with XSockets since there is support for binary frames. So you will not need to send BASE64 encoded strings that are ~36% bigger than the actual image size.

You will also be able to pass metadata along with the binary frame since there are support for that as well in XSockets.

Docs about sending binary data: http://xsockets.net/docs/4/binary-data

I am no SignalR expert, but my guess is that you will BASE64 encode your image and wrap it in JSON since that is what SignalR accepts. If you need help with sending images in SignalR, check out the SignalR room on jabbr https://jabbr.net/#/rooms/signalr

EDIT1: Let me know if you are going for XSockets and need a sample. I can create a really simple sample in that case...

EDIT2: Ok, so I created a simple solution that you can download from my dropbox (for a while). Link: VisualStudio SLN

There is not to much code. If you run it dorectly you will need to have a fodler under c:\temp\images, then just drop images into that folder and they will appear in the browser on every connected client. Notice that you also will get the filename with the message since xsockets support metadata attachments...

FileSystem Watcher

/// <summary>
/// This will be a singleton since the range is internal. You cant connect to this controller.
/// </summary>
[XSocketMetadata("ImageWatcher", PluginRange.Internal)]
public class ImageWatcher : XSocketController
{
    private ImageController imageController;
    public ImageWatcher()
    {
        imageController = new ImageController();

        var watcher = new FileSystemWatcher
        {
            Path = @"c:\temp\images\",
            NotifyFilter = NotifyFilters.LastWrite,
            Filter = "*.jpeg"
        };
        watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;            
        watcher.Changed += watcher_Changed;
        watcher.EnableRaisingEvents = true;
    }

    void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        try
        {
            var blob = File.ReadAllBytes(e.FullPath);
            var metadata = new { filename = e.Name };
            imageController.InvokeToAll(blob, metadata, "newimage");

        }
        catch
        {

        }
    }
}    

Controller

/// <summary>
/// Simple controller that the users will connect to.
/// It does not even have a method in this sample...
/// 
/// The ImageWatcher class will send images to the clients when you drop a imagein c:\temp\image
/// </summary>
[XSocketMetadata(PluginAlias = "image")]
public class ImageController : XSocketController
{

}

JavaScript/HTML

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>    
</head>
<body>
    <img id="latestImage">
    <p id="filename"></p>
    <script src="Scripts/XSockets.latest.js"></script>
    <script src="Scripts/jquery-2.1.1.js"></script>
    <script>
        var conn
        $(function() {
            conn = new XSockets.WebSocket('ws://127.0.0.1:4502', ['image']);

            conn.controller('image').on('newimage', function (b) {
                console.log(b);

                $('#filename').text(b.data.filename);

                var uint8Array = new Uint8Array(b.binary);
                var arrayBuffer = uint8Array.buffer;
                var blob = new Blob([arrayBuffer], { type: "image/jpg" });
                var blobUrl = window.URL.createObjectURL(blob);
                $("#latestImage").attr("src", blobUrl);
            });
        });
    </script>
</body>
</html>

Thats basically all there is to it. The filesystem watcher is a little weird, but it was just to show you a sample...

Uffe
  • 2,275
  • 1
  • 13
  • 9
  • I am more than happy to use XSockets if it is as viable as you say and some example code would be much appreciated :) – const_ref Sep 08 '14 at 16:00
  • The code looks code however I cant get it to display the images I drop into c:\temp\images\. It doesnt ever seem to hit a breakpoint in the controller either. I have tried to run both the .server and the .web project. The server project returns a null on container.Start() and the .web project runs but doesnt display any images on the web page when they are dropped in. Any idea whats wrong? – const_ref Sep 10 '14 at 07:05
  • Guessing that windows blocker the files in the zip... Right click and choose unblock. Then unzip – Uffe Sep 10 '14 at 10:41
  • I have tried that. Do I need a owin startup or a xsockets web bootstrapper maybe? – const_ref Sep 10 '14 at 11:00
  • Nope, in this sample teh server runs as self-hosted. Running it right now on my machine – Uffe Sep 10 '14 at 11:43
  • Hmm, strange. The watcher event is never fired. Tried creating new jpeg files as well as dragging them over etc. – const_ref Sep 10 '14 at 11:58
  • Did you get the server started? If so just use the code in the fsw to send any image – Uffe Sep 10 '14 at 13:14