Skip to content

Instantly share code, notes, and snippets.

@diousk
Forked from hexcowboy/offset.md
Created December 12, 2024 16:08
Show Gist options
  • Save diousk/6eb26cb8a0b921eb22b3781a84c56c3d to your computer and use it in GitHub Desktop.
Save diousk/6eb26cb8a0b921eb22b3781a84c56c3d to your computer and use it in GitHub Desktop.
Twitch Helix API - Get Video/VOD Offset and Comments from Clip ID

Since Twitch decomissioned API V5, there's no correct way to get the VOD offset for a clip. So I just inspected what the Twitch web app was doing and came up with a super cool hack.

I know this looks really complicated but really it just does two things. First it gets the clip information from the official API, then it uses Twitch GraphQL API to get the offset.

kimne78kx3ncx6brgo4mv6wki5h1ko is the Client ID that the Twitch web app uses. It can be used to access Twitch's GraphQL API (undocumented & not for public use). The postData variable contains a request and a sha256Hash. The sha256Hash is basically a job ID and may change in the future, but I added the current hash which should work for all clips as of posting this.

const clientId = "" // Put your Twitch Client ID here
const clientSecret = "" // Put your Twitch Client Secret here

// Generates a Twitch Bearer token from your Client ID and Secret
const {
    data: {
        access_token
    }
} = await axios.post(`https://id.twitch.tv/oauth2/token?client_id=${clientId}&client_secret=${clientSecret}&grant_type=client_credentials`)

// Gets the clip information from API Helix
const clipId = "CarefulRoundFloofSoonerLater-JShSibkZfWy2CjWR"
const {
    data: {
        data: [clip]
    }
} = await axios.get(`https://api.twitch.tv/helix/clips?id=${clipId}`, {
    headers: {
        "Authorization": `Bearer ${access_token}`,
        "Client-ID": clientId,
    }
})

// Gets the clip offset from Twitch GraphQL
const postData = [{
    "operationName": "ClipMetadata",
    "variables": {
        "channelLogin": clip.broadcaster_name,
        "clipSlug": clip.id
    },
    "extensions": {
        "persistedQuery": {
            "version": 1,
            "sha256Hash": "ab70572e66f164789c87936a8291fd15e29adc2cea0114b02e60f17d60d6d154"
        }
    }
}]
const {
    data: [{
        data: {
            clip: {
                videoOffsetSeconds
            }
        }
    }]
} = await axios.post("https://gql.twitch.tv/gql", postData, {
    headers: {
        "Client-ID": "kimne78kx3ncx6brgo4mv6wki5h1ko"
    }
})

console.log(videoOffsetSeconds)

Additionally you can now grab comments for the Twitch clip by using the offset and the kimne78kx3ncx6brgo4mv6wki5h1ko key.

const {
    data: comments
} = await axios.get(`https://api.twitch.tv/v5/videos/${clip.video_id}/comments?content_offset_seconds=${videoOffsetSeconds}`, {
    headers: {
        'Client-ID': 'kimne78kx3ncx6brgo4mv6wki5h1ko'
    }
})

console.log(comments)

Bonus: Limit comments to only the ones within the clip's duration

By default, the previously mentioned /comments endpoint returns all comments after the provided for the offset, and even some before the offset. You can filter the array by using the following snippet to only show comments that were posted during the clip.

// Get only the comments we need for the clip
const videoOffsetSecondsEnd = videoOffsetSeconds + Math.ceil(clip.duration)
const result = comments.filter(
    (comment) => comment.content_offset_seconds <= videoOffsetSecondsEnd && comment.content_offset_seconds >= videoOffsetSeconds
).sort(
    (comment) => comment.content_offset_seconds
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment