如何使用 Mixer Api 显示来自用户的最后 (n) 个流(链接)

How to display the last (n) of streams (links) from a user using the Mixer Api

TLTR:

从这个 (https://mixer.com/api/v1/channels/44877492/recordings) api 端点我收到这个值:

id:302772586(举例)

但我需要的是这个:

https://mixer.com/CalypsoVibes?vod=2ArYJv4YfEaJezssnJR15Q

其中 CalypsoVibes 是用户名(我把我 return 来自另一个端点 (channels/) 的 id 和 vod id 与整数不同。

长话短说(不短):

我正在构建一个部分来显示来自使用混音器 api.

的用户的过去 (n) 个流及其 link

让我们开始说吧,我什至不知道那个网站的存在,所以理解我需要什么数据真的很有挑战性。

这是我的脚本,然后我将解释其功能:

$(() => {
    let mixerAPI = 'https://mixer.com/api/v1/';
    let streamName = 'GrimlockePrime';
    let apiCall = mixerAPI + "channels/" + streamName;

    function makeAjaxCall(url, methodType, callback){
        $.ajax({
            type: 'GET',
            url : url,
            method :  methodType,
            dataType : "json",
            success : callback,
            error : function (reason, xhr){
                console.log("error in processing your request",reason);
            }
        })
    }
    makeAjaxCall(apiCall, "GET", function(respJson){
        console.log(respJson.id);
        let streamscall = mixerAPI + "recordings/165804890";
        console.log(streamscall);
        
    })

});

从这一点开始,我将进行另一个 ajax 调用,使用用户频道的 ID 并将其放入记录端点,以获取此结构:

https://mixer.com/api/v1/recordings/channelId

想法是从用户收集最后 (n) 个流。

因此,从 mixer.com 上的用户配置文件开始,例如 https://mixer.com/CalypsoVibes,我想收集最后 (n) 个流,它们位于该部分的底部并且是称为“过去的流”。

所有资源都是这种结构

https://mixer.com/CalypsoVibes?vod=um8Nx4dNnUqj8E0jcDXKEw

所以我可能需要视频 ID (?vod=id)。

奇怪的是,我无法在混音器 api 文档中找到任何相关参考。所以我并不是 100% 确定我正在寻找正确的端点。

有几个可以胜任这份工作:

1.https://mixer.com/api/v1/channels/userId/recordings 2.https://mixer.com/api/v1/recordings/id

它们都将 return vod 值,但需要注意的是,它们不会 return 任何 id 或任何有用的 link:

https://vodcontent-6001.xboxlive.com/channel-46362-public/7200a34f-7eca-4f81-822f-677afd4a8d97/

这只是 return 的一个示例,但 url 末尾的 ID 与应用程序中的任何 link 都不匹配。

有人遇到过这个问题吗?

Mixer 上的 VoD 有一个 id,这是一个整数,它们有一个 contentId(在第 2 季中引入)和 v2 API), which is a UUID(或 GUID,如果您愿意) . UUID 也可以表示为 base64 字符串,这就是 link 到 Mixer.com 上的 VoD 使用的 VoD ID。 在您的示例中,2ArYJv4YfEaJezssnJR15Q26d80ad8-18fe-467c-897b-3b2c9c9475e5 相同。 如果您有此 ID,则可以在 v2 API 上请求 GET /vods/{contentId},它在 JSON 响应的 contentLocators object 字段中包含各种格式。它们是描述性的,包括完整的 URL 视频和缩略图内容,但缺少 VoD 聊天记录。

您也可以使用旧版 v1 API。就个人而言,这就是我推荐的。 对于任何给定的通道,您首先会在对列表的响应中向 GET /channels/{channelIdOrToken} to then grab the channel ID from the id property of the JSON response. Then you make a request to GET /channels/{channelId}/recordings, passing a query string of where=state:eq:AVAILABLE&order=createdAt:desc (pick only those which are available, not processing or already deleted, and order them most recent to oldest) to grab a list of VoD stream recordings. Append the Recording 发出请求,然后检查 X-Total-Count HTTP 响应 header,如果它大于 50,并且你已经得到了 50 个项目的响应,添加一个带有页面计数器的 page 查询字符串参数并递增 1(从默认值 0 开始)并重复这个过程,直到你得到所有的。 然后,您可以获取录音列表并检查每个录音的 vods object 字段。应该有 4 个项目,每个项目的 format 字段为 hlsthumbnailrawchat。 您将获取每个文件的 baseUrl,并附加以下文件名以获取其对应的文件:

  • hlssource.m3u8(包含对实际传输流文件的进一步引用,这些文件也可在此 baseUrl 中找到,但您可能不想处理它)
  • thumbnailsource.png,如果data.Has720pPreview属性是true,也是720p.jpg
  • rawsource.mp4(这是网站上提供给您的文件,作为您自己频道的下载选项,或者在所有频道上为具有 [=47= 的用户提供的下载选项) ]、FounderGuardian 个角色)
  • chat: source.json(这是一个带时间戳的聊天记录,它包括所有未被删除的消息,以及用户加入和离开事件)

您可以找到使用 v1 API 嵌入来自 LevelUpCast into jPlayer here.

的 50 个最新 VoD 的示例

$(document).ready(function ()
{
    $form = $('#vod-form');
    $form.on('submit', function (e)
    {
        e.preventDefault();

        var channel = $form.find('input[name="channel"]').val();
        var beamApiBase = 'https://mixer.com/api/v1';
        var channelToken;
        var channelId;
        
        var vodListArray = [];
        function getVod(page)
        {
            $.ajax({ 
                url: beamApiBase + '/channels/' + channelId + '/recordings?where=state:eq:AVAILABLE&order=createdAt:desc&page=' + page,
                success: function (data, textStatus, xhr)
                {
                    for (var i = 0; i < data.length; i++)
                    {
                        if (data[i].state != 'AVAILABLE') // API is silly sometimes and ignores the query... ‍♀️
                        {
                            continue;
                        }
                        var thatVod = data[i];
                        var vodPaths = {
                            stream: null,
                            thumbnail: null,
                            small_thumbnail: null,
                            snapshot: null,
                            download: null,
                            chatlog: null
                        };
                        for (var j = 0; j < thatVod.vods.length; j++)
                        {   
                            var thisVod = thatVod.vods[j];
                            switch (thisVod.format)
                            {
                                case 'hls':
                                {
                                    vodPaths.stream = thisVod.baseUrl + 'manifest.m3u8';
                                    break;
                                }
                                case 'thumbnail':
                                {
                                    vodPaths.thumbnail = thisVod.baseUrl + 'source.png';
                                    if (thisVod.data.Has720pPreview)
                                    {
                                        vodPaths.snapshot = thisVod.baseUrl + '720.jpg';
                                        vodPaths.small_thumbnail = thisVod.baseUrl + '168p.png';
                                    }
                                    break;
                                }
                                case 'raw':
                                {
                                    vodPaths.download = thisVod.baseUrl + 'source.mp4';
                                    break;
                                }
                                case 'chat':
                                {
                                    vodPaths.chatlog = thisVod.baseUrl + 'source.json';
                                    break;
                                }
                                default:
                                {
                                    console.warn('Unknown VoD format', thisVod);
                                    break;
                                }
                            }
                        }
                        data[i].vodPaths = vodPaths;
                        var thisVodItem = {
                            'title': thatVod.name,
                            'artist': channelToken,
                            'date': new Date(Date.parse(thatVod.createdAt)),
                            'duration': thatVod.duration + 's',
                            'urls': vodPaths
                        };
                        vodListArray.push(thisVodItem);
                    }
                    if (data.length == 50 && xhr.getResponseHeader("X-Total-Count")*1 > 50)
                    {
                        getVod(page + 1);
                    }
                    else
                    {
                        if (vodListArray.length > 0)
                        {
                            var $vodList = $('#vod-list');
                            var $table = $('<table>');
                            var $tableTitleRow = $('<tr>');
                            var $tableItemNumberColumn = $('<th>');
                            $tableItemNumberColumn.text('Item #');
                            $tableTitleRow.append($tableItemNumberColumn);
                            var $tableThumbnailColumn = $('<th>');
                            $tableThumbnailColumn.text('Small Thumbnail');
                            $tableTitleRow.append($tableThumbnailColumn);
                            var $tableTitleColumn = $('<th>');
                            $tableTitleColumn.text('Title/Name');
                            $tableTitleRow.append($tableTitleColumn);
                            var $tableDateColumn = $('<th>');
                            $tableDateColumn.text('Date');
                            $tableTitleRow.append($tableDateColumn);
                            var $tableLinksColumn = $('<th>');
                            $tableLinksColumn.text('Links');
                            $tableTitleRow.append($tableLinksColumn);
                            $table.append($tableTitleRow);
                            for (var i = 0; i < vodListArray.length; i++)
                            {
                                var $tableRow = $('<tr>');
                                var $tableColumnItemNumber = $('<td>');
                                $tableColumnItemNumber.text(i + 1);
                                $tableRow.append($tableColumnItemNumber);
                                var $tableColumnThumbnail = $('<td>');
                                var $thumbnail = $('<img>');
                                $thumbnail.attr('src', vodListArray[i].urls.small_thumbnail);
                                $tableColumnThumbnail.append($thumbnail);
                                $tableRow.append($tableColumnThumbnail);
                                var $tableColumnTitle = $('<td>');
                                $tableColumnTitle.text(vodListArray[i].title);
                                $tableRow.append($tableColumnTitle);
                                var $tableColumnDate = $('<td>');
                                $tableColumnDate.text(vodListArray[i].date.toLocaleDateString() + ' ' + vodListArray[i].date.toLocaleTimeString());
                                $tableRow.append($tableColumnDate);
                                var $tableColumnLinks = $('<td>');
                                var $streamLink = $('<a>');
                                $streamLink.text("HLS Stream");
                                $streamLink.attr('href', vodListArray[i].urls.stream);
                                var $videoLink = $('<a>');
                                $videoLink.text("Video Download");
                                $videoLink.attr('href', vodListArray[i].urls.download);
                                var $chatLogLink = $('<a>');
                                $chatLogLink.text("Chat Log");
                                $chatLogLink.attr('href', vodListArray[i].urls.chatlog);
                                var $thumbnailLink = $('<a>');
                                $thumbnailLink.text("Thumbnail");
                                $thumbnailLink.attr('href', vodListArray[i].urls.thumbnail);
                                $tableColumnLinks.append($streamLink)
                                $tableColumnLinks.append($('<br>'));
                                $tableColumnLinks.append($videoLink);
                                $tableColumnLinks.append($('<br>'));
                                $tableColumnLinks.append($chatLogLink);
                                $tableColumnLinks.append($('<br>'));
                                $tableColumnLinks.append($thumbnailLink);
                                $tableRow.append($tableColumnLinks);
                                $table.append($tableRow);
                            }
                            $vodList.empty();
                            $vodList.append($table);
                        }
                    }
                }});
        }
        $.getJSON(beamApiBase + '/channels/' + channel, function (data)
        {
            channelToken = data.token;
            channelId = data.id;
            getVod(0);
        });
    });
});
body
{
    font-family: sans-serif;
}
table, tr, th, td
{
    border: 1px solid;
}
<script src="https://zeptojs.com/zepto.min.js"></script>
<form id="vod-form">
    Channel Name or ID: <input type="text" name="channel" length="20"></input>
    <input type="submit" value="Get list"></input>
</form>
<div id="vod-list">
    <p>The list will appear here.</p>
</div>