companion
companion copied to clipboard
Refresh PNG icons
Is this a feature relevant to companion itself, and not a module?
- [X] I believe this to be a feature for companion, not a module
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the feature
An internal action to "refresh" a button PNG or all of them.
Usecases
When working in different projects, sometimes we use thumbnails to show on the button the graphics that will be triggered. Usually we have a Streamdeck base layout that uses the same structure but the graphics change between projects and we managed to create a companion button to generate a thumbnail of the desired video inputs (vMix layers in our case) replacing the old ones. Aauto updating those button PNGs with an action, not just changing them manually every time, could save a lot of time on the preparation.
By refresh, do you want it to fetch the new png from the same path on disk, or should it be looking somewhere else?
Companion doesnt know where they originally resided on disk because the ui where you choose it runs in your browser (which could have been done from another computer entirely).
Perhaps it would work for you to write a script which pushes the new pngs to the http endpoints?
Its not fully documented, but the docs do say for other style properties. A GET request to /style/bank/2/4/?png64=<PNG DATA>
, where <PNG DATA>
is a base64 encoded png image should work
For me it has more sense to fetch from the same path on disk, so any change to the images would be updated in a faster way than looking somewhere else. The script way seems more complicated as the images should be also converted to base64, which companion does when charging a PNG
A GET request to
/style/bank/2/4/?png64=<PNG DATA>
, where<PNG DATA>
is a base64 encoded png image should work.
I have tries this and it doesn't seem to work! :( Any ideas?
So, I got this working, and it took me a couple hours longer than I care to admit because I forgot to encode the Base64 data, resulting in a PNG ERROR message.
Here are the steps:
-
Convert your PNG to a Base64 image. This requires a Base64 image not just the Base64 string. In plainer words, it has to be a Data URL. So, you want it in this form:
data:image/png;base64,<PNG DATA>
-
Encode your Base64 image so it can be sent as a URL parameter. In JS, you want to use encodeURIComponent().
That's it. Well, almost. The other issue I ran into is that a button has to exist already for you to be able to push an image onto it. That's true for any of the properties, so, I found that issue early on when image and text were both not working. After a couple of hours of trial and error, I dug into the internals of Companion (specifically the db file where button configs are stored) and realized that my Base64 PNG was corrupted.
Here's an example (note: this example sets every button property available, but you can send whichever ones you want to send):
/style/bank/2/4/?text=&alignment=center:center&size=14&color=%23ffffff&bgcolor=%23000000&pngalignment=center:center&png64=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEgAAAA6CAYAAAATBx%2BNAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAubSURBVHhe7ZsJdFTVGce%2FWZLJnkBICAGBmACRXRARpKAiaGU5SqW1pmDBBVyKxZZa6KmoR6QVazyKqKnVgpFFFIW0sikeLFgEkcIBDMQkLIkkCEkmk4WsX%2F%2FfnTdDJBPz3psJUQ%2B%2Fc%2F6Td99M7tz3ve9%2B97v3vqFLXOISbYlF%2B9veRELjoeuggVBXKAJqhCqgIugItBvaCh2DfnQEQb2hEdA1UBLUC8qAXBDrVAP0MXQT1Oa0tQdJ%2FROh2dD1UCjUDJvNRiNGjKBbbrmFhg0bRj179qSIiAhiZnK5XFRQUECHDh2i7du305YtW9Q5jdXQ3VCVKv3AEI9ZBak7b7VaOSkpiWEIHj58OHft2pVhBJ45cyZnZ2fDFvpwOp28ZMkSjoqK8njUvyAr9IMhHBoOvQhxTEwMp6enc3FxsXaJ52lsbNSOjHP48GGOj4%2F3GGkPJDfjD5DEsO8lo6D3IXF3T8N506ZN2iUFnlWrVjG6p%2Fe7NElg3wldC%2FlNIGKQuPdz0BzIIvGkf%2F%2F%2BlJKSQqNHj6Y5c%2BR02yHxKT8%2Fn%2FLy8mjnzp20bt06Onv2rLwlwfwh6BUptCcLIQ4JCeGFCxdyUVGRdn%2Fbh4qKCp4%2Ff76KeWhXPSTdvd2QeOOSxmB00Zr4%2FWDevHmeLve6NNQs%2Fkb%2F7lBEcnIyjRs3zn3me4J0bw1JOtuNKKjabrfz7t27tXunnwMHDnBhYaFW8s2uXbu4rKxMK%2BmjqqqKx4wZ4%2FGgp6Sh7Uk6pIbzZcuWcWVlpdbM72bPnj0cFBTEcXFxnJGR8a004MyZM7x%2B%2FXqeMGGCukh4A1dXV2vvtkxdXZ36vwEDBniMUwjFQaYJxCgWDC2H7pACEjgaOXIk9erVS2XDPXr0oKFDhxISQ5Uxw2MIQz8h2aPS0lL5FwXiGIWHh6vsGR5AyJG0d9wMHjyYFixYQGPHjiXcDIIxVHYNg1BJSYkayeBtnhFMkLnbbdCXqtTOiKGnQMchz91rVVOnTuXMzExG%2FOLIyEjvecmwR40axYsXL%2BZt27YxYpz3Pcl7JIuWUdNz7gLVQI9CPqc17cUwaDPkbWhirI1H9Xd4y3JR0p369u3L06dP582bN7v7hYZk1TKNKC8vb5ZhS0xZunSpMpoY0mKxeOuNjbJy7252tlrOfzcks%2F8%2FQhIj250FkOQbHBVm5fsnR%2FD29Hgu3dCNy7K68cRrQlWjZ8yYoV2uf0icOXr0qPIgC4yStSiOnfiew2904Wfui%2BGkLvamhiqBUqF2QzynDlINSuho42njwnnxPTH82u87cm5mIu%2FLSGCblRjxRXlIIJDJqnzfBBhfjLP%2F7wk8op%2BDO8Kb0NebGki0HWqXyazEnR0Qj7sugpN7Bl%2FYMO6ZYOfT73ZVjZfy2rVrtUv0D1kRkPoyF8QqA6WNDVdl8ajoKBuPvz6Clz2byAnxXm%2F6BXTR%2BSnEnePsXJp3BdcW9ePdH17Ozz%2FdhX9zbywn9XAbbPakCH78rmh1PGvWLO0SzSM5kaQHjiAL%2F3dpZ54%2BPlwZJjjYwru3Xs41p%2Fpx%2FWm3Xn0u0WMgGcls0EVFVvV4yRMJ3gY11X%2F%2BncQOhzuYpnYPUn8HDRqkXaY%2BXC4XL1q0SAV2pA6clpbGkydPVnVJUPYE5hB8z4pl3Zq1ofrrvk09W4b8i4YEvsaoSCuX5F7RrGEebXirO8tn8Fklh8PBq1ev9rk25KG2tpZ37NjBc%2BfO5djYWO%2F%2F%2BlJEuJV%2FNTWGD%2B5M8fn9ovRFCZ7Pb4IMYzZRfAJ6bGZaB8pIT3SfaYETBXX0p6eKae2Gcqqvl3a6SUxMVElkdHQ0YUQiZMpUVFREOTk5KlH0cOXAEJr%2F2ziCl1DB1%2FVUU9tIHaJt1DvFQYP6hRC8VPukb0pKG6j7wCN0roZlpL0MkhRAN2YNtA8avPHtHoQA7T7TCnnHa2nVu07a9FEF7TtQLQ3W3vk2iCd0WdcguumGCLrzZzE06powdc4fJqedoA%2B2qnXsmdAbcqAXM18tc5tT4WFWW3F2Ku6%2B8SpqYJz8E7V0srCOKisbqQGzCsxCKLaDnVIuD6Yune3aJwPDsn%2BU0Jz5p%2BQwE5omB3oxY6CboY2jR4TRtvWyc6MPTLFgCCa7zT93MFPP%2FoPnaOgNuXJ4FOojB3oxk0D1k5eB6P96WbGmjPoMz6G4Xtk06c7jdPyk5JbGkXpSvfWc0F1Pam8HIQ2QwxRIf8OBGQMpt0lOkkl860jMuXtOIeUdqyVXRSNt%2FLBCGamuScDWg6eeXG89Lpr4y%2BNU39B6PQ4Yp1ui7EKp65VFPt2YMZBaX0GCqAqt8ebbZapbNOXwkRra%2B79qraQPX%2FV8ebSGPt%2Bnr54m7TW0PmTGQLIOTchBVKE1LrwoDy2dbwl%2F62nSXtV%2BvZgxkCHuvD262TCd2stBVw02tlyT5qOePsiFhl3Ztss%2BZgyksrgKDM96mDg%2Bkl7%2BW6LKbYKCLDR2dDghw1bHRpgg9TyLehBLPPVkrexOdru%2BeiSd0DC0j2%2BslW6WQg8ihSdMSt1ndCBdQWT102fN1tPn6hwV4OUQkuFeF2aaq57NyTtmbKiW7uGvcQQz9WB6h2mKaq%2B40Qk50IuZJh%2BSl%2F2HzqlCICkta1DZtVxQIMnOqcEcTtUp2aKhhpsx0F6oYe%2F%2BludTRnkHE9lhN%2BZS59RsSrryKMX3yaYZDxWqiW4g2PmZN%2BzIE2qGMGOg09BBCXo7dlW6z5hEYsnDC07RHfecxAT2HHl2emQAkLznqrG5tOtzY%2FmSLzZvk6f4FNu0v7oxGxU2yMva9eWqYJbnXzlLL70m6%2Bq%2BkaWK26adoFPFslJhDum2H36iDCSVbJQDI5g1kHpy7J0NTip36RvuL6T4dD09%2Fldxxu%2Fmm7P19Oeni7WScVa%2B66Rz51QokBVQNaU3glkDyRrvdmd5I73%2B1vndUSP8c3UZVVbpM%2B7qdU7lTUaRBboXM7w7raaeEzJrIOFZ9bL0DFVg8miULefjQqvIYPDJp8bjncSxr%2FJV7iN5jwoLRvHHQB9Anxahqzyd%2Fo37jAGOfCU7xPrJ%2FkpdqG6c5Q302GJvF34cMhXI%2FDGQdOy5UEM6gu3nBmbnMnpVVRvzOr3d0cO8hcWe4C57d2vkwAz%2BGEiQvOKFujqmabMLqMypL05INhwdZWybqkO0%2Fqauec9Jb6xUsVHu2izI3EgC%2FDWQIHvzX%2BTk1VLarAKqhbH0MKCvoYU93Z%2Ff80U13Tf3a%2BWl4BHosDoySSAMJKn77VCxJGQzHiz81vZOS0y8SX6eoY8OMTa6dniYVmqZA5j%2BTE477umOr0F%2BP%2BEaCAMJ%2BdAEqGzN%2B06aOvNk0%2BUFn8j6TkK8vlXJ%2B2d0pLDQ727qDkwnbpxyDHmT6uYyYj0gB%2F4SKAMJMkeTH5icydrkojGT8iknt%2BWRJzzMSi8906XVmXm%2FVAc9%2BnAnrdQc6UqvLi%2Bhm28%2F5smV3oN%2BDgVkIhfoDX15JlDu3jgM%2F52WIxmMirTRkEEhMETzpSdZWUxMCKKtH1dQg4%2F4LnEna2UP6hTr29NkCePX6NLpL5%2Bl%2BgY1qr4A3QsFZpYL2uKJB0ld34QuQ8AesPGjCkvWZpfaVUhJcqgRrClDBobSlIlRajogmblsIA64IoQeeaCTWkGM7di8iSWYX%2F3l%2BTN01wOFdPBLlU%2FJkCW7ppK8mh6xfNH8tgaWWyF5CranFOTC753egabeGkVxLXhFS0hXklxrBbwyc22Z2vrReBuS0Uq8N%2BC0tYEEGZ%2Fl92K%2Fg7rJCZvNQlcPCaUxI8PQ%2FUKpd3IwdUFXCwu1kA1dUfbMnMipjp2so0PZNfTZ3ir66JNKtZimIdaRXx4%2BCX0qJ34MOCAJnlmQJHASM7xC1%2BPgIIt61sduP%2F%2BQ5gU6CckPZ%2FpDF4WL4UG%2BkKdPfwKNhOT3XclQZ0iSHQk64ipOqADKhmSElGcND0ABjTGt0V4G8oUM%2BGIcaZMYwfwq2SUuFkT%2FBzJRNKWFKJBHAAAAAElFTkSuQmCC
I have tried to automate that, with a small powershell script (+ imagemagick) but I always get the following error
- I am using 3.0.0 beta (windows)
- I use the following code
magick.exe convert thessaloniki.jpg -resize 72x58! test.png # run imagemagic to create a 72x58 png image
$header = "data:image/png;base64," # create the header
$t = openssl base64 -in test.png # create the base64 string
$base = [System.Web.HttpUtility]::UrlEncode($header+$t) #url encode the result
$companionURL = "http://127.0.0.1:9000"
$request = "${companionURL}/style/bank/8/2/?text=&bgcolor=%00000000&size=14&png64=" + $base
Invoke-WebRequest $request #invoke the request to companion.
I do not understand why it does not work
Actually I think its a bug. I went through the code and generated the same dataURL that the code does, but going through the GET request it returns an error due to length of the url. (the image is of the correct size)
Probably there should be an option to set the image through a post request.
Following on from some recent core changes, I realised that doing this as part of a module is much simpler than it used to be.
In the 3.0 betas, there is now a feedback for the generic-http
module called 'Image from URL'. This will fetch an png/jpeg from the provided url (supporting variables in the url field), scale and display it.
When the variable changes, it will update with the new url. It can also be set to reload the image on an interval.
I would provide a demo, but my laptop appears unable to record videos today...
It should be possible to do something similar for the generic-filereader
module, to support the flow of reading from disk
This doesn't really solve the original description of this task, as that wants it to be done on-demand rather than automatically. And using this automated polling would be very inefficient as it will be reloading and scaling the image every few seconds
May this also be used for automatically fetching thumbnail button backgrounds for ptz camera presets when saving or updating?
@premultiply
May this also be used for automatically fetching thumbnail button backgrounds for ptz camera presets when saving or updating?
If the images are served over http in some way then yeah it could probably be used. I'm going to use this with the spotify module which provides a variable with the url for album art, but no builtin way to display that
Yes, see https://github.com/bitfocus/companion-module-generic-http/issues/40
@Julusian
That is really a great feature, and could be used as a workaround to populate images to buttons, the drawback would be one custom url per button.
I think there is a very easy fix for the problem.
First of all the problem is caused by the fact that Nodejs limits the http header size to 8Kb (or 16Kb depending on the version).
This is why we get messages that the message is too big. The size can be checked by logging http.maxHeaderSize;
There is a very easy fix for that When launching nodejs add the --max-http-header=size
to change the allowed size.
For example --max-http-header-size=131072
will allow 128KB of header size.
In fact you can make that user defined if you want, but for an easy , zero-line fix, please increase that to 128KB or more to allow larger headers.
I am not sure what changed in the latest beta, but now even the url posted from kbowling76 above does not work. (for the png part)
Hello, any update on this topic? I have been trying the "/style/bank/
In the code I found this and this, but as I said, I cannot get it to update the PNG image. The response is "ok" but it does nothing to the image.
Personally I would like to change the button PNG to match the videogame characters that are being played. So it is easier to see the png image than the text name of the character. So each round I would update the buttons images.
Thanks for your work and consideration. Regards.
@DhSufi Did you ever find a solution to get this working?
@EricAndrechek . No. Waiting for it to be resolved.
@DhSufi Did you ever find a solution to get this working?
No. The Log shows a request received but nothing changes in the WEB GUI. I did not tested it with a streamdeck yet to check if the button changes image in the hardware. But as long as I tested, The WEB GUI changes everything I send the button (text, background color, font size, etc) so I suppose it should change the image when the request is received. Also I tested to send several changes at the same time, and all of them happen in WEB GUI except for the image change. I hope this will be possible in the future because it is extremly powerfull feature for plugins and work flow (in my case change Pokémon each battle and changing League of Legends and TFT champions)
Well I found the web UI's socket connection and can see how it changes the image there, so I guess it would be possible to use that as a janky API to change the image, but I don't feel like that is worth the trouble... hopefully we can just get the normal api working...
Well I found the web UI's socket connection and can see how it changes the image there, so I guess it would be possible to use that as a janky API to change the image, but I don't feel like that is worth the trouble... hopefully we can just get the normal api working...
Can you please show us how to it with a exmaple? Thanks @EricAndrechek
I've got midterms this week that should probably take priority... But sure next week I'll try to make a janky little example script.
OK I got it. Companion UI websocket url is: ws://127.0.0.1:8000 You need to use socket IO and send event and data. The event is: controls:set-style-field' The data is: ('bank:1-14', {"png64": "data:image/png;base64,iVBORw0KGgoAAAAN...}")
Here is a python example:
import socketio
sio = socketio.Client()
data = {"png64": "data:image/png;base64,iVBORw0KGgoAAAANSU..."}
sio.connect('ws://127.0.0.1:8000')
sio.call('controls:set-style-fields', ('bank:1-14', data))
Thanks Eric Andrechek for the hint. I hope it helps Video example for my particular use:
https://github.com/bitfocus/companion/assets/75437459/1a216d22-3634-4e9b-8192-da8ee341581a
It turns out there was a bug which broke setting the png over this api. This is fixed in the betas now. I am currently working on a redesign of the api, which will allow for fixing the url length issue. Hopefully landing soon