Open TianqiMikeHu opened 2 months ago
This is also related to this issue for the clips player. https://github.com/teklynk/twitch_clips_player/issues/13
I was only able to skip/ignore clips that are using the new thumbnail url. However, I see this is an issue when using the !watchclip feature. The shoutouts should function as normal if the channel has older clips since those seem to still use the old thumbnail urls.
There is a discussion about this change/issue. Others are also dealing with the same thing. https://twitch.uservoice.com/forums/310213-developers/suggestions/39228784-extend-clips-api-to-provide-the-mp4-url-so-editors Hopefully Twitch adds a way of getting the clips mp4 for newer clips.
Got it, thanks for the quick response and the info! Well, good to know others are having the same issue with this change.
I think I might have cracked the code on this one? The following solution seems to work fine for me, curious if you can repro.
So first of all, I was pretty convinced there's no similar "thumbnail" workaround possible with the new URLs. I don't think the videos are even stored behind the new domain name. Different origin servers (S3 vs. Nginx), and not to mention the word "static" in the domain name itself.
With that being said, I tried to figure out how the "intended" authentication check works. As you probably know already, with the official Twitch clips player it makes a request to "production.assets.clips.twitchcdn.net" for the mp4 file, which requires a signature & token in the query params. After lots of trial & error, I think I figured out something useful.
I found out the signature comes from an API call to their GraphQL server. You can check any clips.twitch.tv clip with your browser's dev tools open, and in the Networks tab, filter by "gql" (I would also recommend you to do this in an incognito tab. If you're logged in, the request also sends your user ID, which does not appear to be required for the API call to work). Then, find the one where the request payload has "operationName" as "VideoAccessToken_Clip":
From trial & error, the only request header that you absolutely need to set "client-id". For me, this value is always "kimne78kx3ncx6brgo4mv6wki5h1ko" (incognito window, tried different browsers too), so idk if you get the same value too.
The request payload is pretty self-explanatory, with the "slug" being the clip's unique ID. For the persistent query Sha256 hash, I admit I know basically nothing about GraphQL, so I don't know what's the exact string this is computed from, but again the value appears to be the same every time: "6fd3af2b22989506269b9ac02dd87eb4a6688392d67d94e41a6886f1e9f5c00f".
If you check the response of this API call, it gives you a nice json object with the signature you need (and the token to URL-encode). This should allow you to access the video from "production.assets.clips.twitchcdn.net" and pass the authentication check.
Python code example: Note that I hard-coded the client ID and the Sha256 hash. The original unique ID is passed in to the "slug" field. I also faked the user agent but I don't think it matters.
Let me know if this works for you. (And I hope they don't patch this out if this actually works lol)
Just noticed the thumbnail format for newer clips have changed, which does appear to break this tool.
For example, if I use the tool with !watchclip https://clips.twitch.tv/SeductivePerfectClipsdadOneHand-QDHtFh3QBebzcPAV
The getuserclips.php API call returns an empty response (still 200 status code), which then causes the JavaScript console to throw an error like this:
shoutout.js?cachebus…E2eT6xL9aG2yB1f:300 Uncaught TypeError: Cannot read properties of undefined (reading 'clip_url') at shoutout.js?cachebus…T6xL9aG2yB1f:300:33 at xhrV.onreadystatechange (shoutout.js?cachebus…T6xL9aG2yB1f:230:17)
I don't really use this tool myself, but I just noticed my own implementation appears to be broken too, so I looked up some popular tools from a Google search to confirm whether other people's tools are affected too, which does seem to be the case.
For me, I just derive the clip URL from the thumbnail URL, I assume this tool has a similar approach? To demonstrate the difference, if I call Twitch's Get Clips API on the above clip, the thumbnail is:
"thumbnail_url": "https://static-cdn.jtvnw.net/twitch-clips-thumbnails-prod/SeductivePerfectClipsdadOneHand-QDHtFh3QBebzcPAV/b46f9699-bbd3-4b7f-96af-05b0bdaea68b/preview-480x272.jpg"
Compared to an older clip: https://clips.twitch.tv/OriginalEasyEndiveBloodTrail-r-MGj69BnciPyb1O
"thumbnail_url": "https://clips-media-assets2.twitch.tv/G5DtLq_jBo-vQZ3Ij8m9Tg/AT-cm%7CG5DtLq_jBo-vQZ3Ij8m9Tg-preview-480x272.jpg"
Unfortunately, I haven't been able to figure out any new workaround, so idk if there is a solution for this.