Any tips on passing the review process are helpful.
I’ve added detailed review details and made a guideline video.
So far here are some things that I’ve implemented and fixed plus this might help others.
- First Include: In my viewer.html make sure the extension helper is the first script included.
<script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
-
Status Messages: I’ve added a ton of status messages in the extension. Previously I had a minimal UI that identified the ‘broadcaster’ and ‘viewer’. Now I have a bunch of status methods that appear based on feedback from the extension backend service. I’ve even added timeout detection with the EBS with a status message for that. This should also avoid the rejection based on feedback that the extension doesn’t do anything.
-
Skin: The initial backend service was the vanilla Windows.Forms. I’ve converted to WPF and skinned things to look a bit better.
-
Hardware: My extension depends on LED hardware. There’s an emulator available that shows the LED lighting if the review team doesn’t have a Chroma enabled device. You can find the supported devices here.
http://developer.razerzone.com/works-with-chroma/compatible-devices/ -
Only the broadcaster can talk to the EBS. Yes only the broadcaster communicates with what I’ve called the
ChromaRelay
backend service.
Video sync: I’m thinking I might need another video to show what it’s like for the viewer receiving video with Chroma data. I’ll get on that. It takes a couple computers since review needs two accounts for a ‘broadcaster’ and ‘viewer’.
- (continued) More about #5. Technically I do have the
viewer
talking to theChromaSDK
REST API to display the Chroma lighting. This is the niceHTTPS
REST interface between the browser and the lighting hardware.
https://assets.razerzone.com/dev_portal/REST/html/index.html
Strictly speaking I may be violating the rules, but it’s necessary to talk to the lighting hardware so the viewer can have their lighting synchronized with the video.
-
WebWorkers - Regarding JS/HTML5 I’m using
setTimeout
andsetInterval
to sync things. I’m pretty sure I need to switch over to WebWorker so I can have reliable timing. -
Video latency - Using the context event you can get the
hlsLatencyBroadcaster
which gives you how many seconds theviewer
is behind the live stream. Using this latency you can pad your receive buffer so that your extension messages are in sync with the video. In my case each second of data includes a set of 10 data samples that have a 100 ms duration each. So I’m enforcing that the receive buffer always has (10 data samples for every second of latency).
window.Twitch.ext.onContext(function(context, contextFields) {
//console.log("context", context);
//console.log("contextFields", contextFields);
if (context != undefined && context.hlsLatencyBroadcaster != undefined) {
receiveLatency = (context.hlsLatencyBroadcaster) * 10; //100 ms intervals
if (receiveLatency < 0) {
receiveLatency = 0;
}
//add latency
while (receivedBuffer.length < receiveLatency) {
receivedBuffer.push(undefined); //100ms intervals
}
//cap the buffer length to maintain sync
while (receivedBuffer.length > 0 &&
receivedBuffer.length > receiveLatency) {
receivedBuffer.splice(0, 1);
}
}
});
- Compression - Broadcasting has a 5kb limit per request per second when sending data. I have my extension backend service sending the data, and to get to the 5kb limit the service is doing compression. The EBS is C# and so I’m using SharpZipLib to compress the message. The data contains arrays of RGB data. When sending the values as RGB comma delimited arrays compression could only get down to around 7.5kb. And that’s the largest size when all the colors in every frame on every device are different. Technically it was 5kb, but when you base64 the compressed binary data it ballons by 30%. I found I could further reduce the final size by separating the RGB comma delimited arrays into R, G, B comma delimited arrays. And that’s because there’s more common data when you break RGB integrer values into their red, green, blue component parts. And since compression is being used on the backend, I’m also using decompression in the frontend javascript. I used
JSZip
for that.
-
HTTPS Secure - The extension backend service communicates with the frontend by running a secure HTTP server on the backend. For browser security this means that the backend needs to run HTTPS. This means that you need to obtain a trusted certificate for your domain. You can find certificate authorities that are paid or even free so you can acquire a trusted certificate.
-
Installer - I use InnoSetup to build the application installer. The installer also needs to manage installing the certificate from step 9. You’ll get a certificate and key from your certificate authority which can be combined into a PFX file which can be installed on the command-line by the installer.
-
Extension Icon - I replaced the default extension icon with a custom icon.
Rejection 1:
These two things were straightforward to fix.
Rejection 2:
What does the forward-facing comment mean? I can add a link to the extension backend service to the config section. For now it’s a dropbox link. Should I be bundling the application installer in the extension zip when I upload the extension files. That way the link would be relative instead of a dropbox link?
I’ve linked to the dropbox download from the config.html
for the time being. And I whitelisted the link in the extension settings so the download can work.
Yes only broadcasters would use the extension backend service.
I’ve expanded the description and links on the config.html
page.
If they only saw Viewers
in the extension, that means they didn’t test with a broadcaster
and viewer
account. I made a video to show how this works. And with the status messages it should be more apparent about what’s going on. Now they’ll see the viewer
with a messages for ‘Waiting for Chroma data…’ or ‘Receiving Chroma data…’. While the broadcaster
will display either ‘Waiting to send Chroma data…’ or ‘Sending Chroma data…’.
Rejection 3:
In order to connect with the Chroma REST API, the ChromaSDK
needs to be installed.
Users with Chroma hardware would have the Razer Chroma SDK Server
service installed.
I’ve added more detection logic to detect if the ChromaSDK
is missing to display a status message.
I can simulate this scenario by stopping the Razer Chroma SDK Server
service before loading the viewer
page for broadcaster
and viewer
.