We have a Vision project that has pop-up windows with the video player component showing live video stream from an industrial camera. We recently changed cameras to a new one with better resolution and image capture. However, we started testing and realized this new one supports MJPEG but only via websocket. It has a connection url of “ws://:8888/ws”. The older one had an actual http url. I got some example html code from the manufacturer for using the websocket in html (below). Is there a way in Ignition to use this html to display the video feed?
MJPEG Livestream
#mjpeg-stream {
width: 100%;
height: auto;
max-width: 1280px; /\* Adjust as needed \*/
}
MJPEG Livestream
<script>
const img = document.getElementById('mjpeg-stream');
const ws = new WebSocket('[ws://192.168.136.100:8888/ws](ws://192.168.136.100:8888/ws)');
ws.binaryType = 'blob';
ws.onmessage = function(event) {
const url = URL.createObjectURL(event.data);
img.src = url;
};
ws.onerror = function(error) {
console.error('WebSocket Error: ', error);
};
ws.onclose = function() {
console.log('WebSocket connection closed');
};
</script>
Here is the actual full html code that I received.
If you have the web browser component for Vision, maybe try setting it to HTML mode and placing the example HTML in the startingHTML property?
1 Like
We didn't communicate it out much, but as part of an effort to simplify our module lineup in 8.3 the Vision module now automatically includes the Web Browser component.
2 Likes
Thank you! This worked perfectly. We are also developing a Perspective version of this application. Does the Perspective Video Player support MJPEG via websocket, or is there a way to embed an html webpage with the same html code?
You can't embed the same HTML exactly, but you could use the Markdown component with the 'escape HTML' option turned off to embed that Javascript onto the page. It's very simple code: just creating a websocket and immediately dropping each returned message onto an image. An LLM should be able to do it with some prompting.
What is the best way to make the html code dynamic and pass in the IP via a parameter? I have the Web Browser object on a pop-up window that can get called for different cameras. I tried an Expression binding on the startingHTML property, but it does not like the formatting of the html text and gives me unterminated string errors.
Take your sample HTML and put it into a text editor. Replace all single quotes ' with double quotes ", including inside the actual script body.
Use an expression binding and the stringFormat function, wrapping the entire HTML text as a string literal using single quotes.
That is, your 'raw' HTML would be something like:
<html lang="en">
<script>
const img = document.getElementById("mjpeg-stream");
const ws = new WebSocket("%s");
And then your Ignition expression is:
stringFormat('
<html lang="en">
<script>
const img = document.getElementById("mjpeg-stream");
const ws = new WebSocket("%s");
',
{path/to/property/with/ip}
)
That should work:
- HTML requires double quotes
- JS treats single quotes and double quotes the same
- Ignition's expression language treats single and double quotes the same
So as long as you're consistent about the outermost layer being single quotes, everything within it will be a single string to the expression language.
I’m still getting the “unterminated string at end of line” error, line 1 character 15- basically the end of the stringFormat(‘ line.
For some reason the editor is not allowing a string to get split to multiple lines. I got it to work by going back to the originally formatted html code and splitting it into 3 custom string properties. I have the html right up to the URL, then a property for the URL, then one for the code after it. The URL property gets passed into the popup window. The startingHTML property of the Web Browser object has an expression that is simply concatenating them all together.
1 Like
Oh, right, duh. I'm too used to Java/Kotlin, forgot our expression language doesn't do multiline strings like that. Glad you got something working.