如何使用 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。
在您的示例中,2ArYJv4YfEaJezssnJR15Q
与 26d80ad8-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
字段为 hls
、thumbnail
、raw
或 chat
。
您将获取每个文件的 baseUrl
,并附加以下文件名以获取其对应的文件:
hls
:source.m3u8
(包含对实际传输流文件的进一步引用,这些文件也可在此 baseUrl
中找到,但您可能不想处理它)
thumbnail
:source.png
,如果data.Has720pPreview
属性是true
,也是720p.jpg
raw
:source.mp4
(这是网站上提供给您的文件,作为您自己频道的下载选项,或者在所有频道上为具有 [=47= 的用户提供的下载选项) ]、Founder
或 Guardian
个角色)
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>
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。
在您的示例中,2ArYJv4YfEaJezssnJR15Q
与 26d80ad8-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
字段为 hls
、thumbnail
、raw
或 chat
。
您将获取每个文件的 baseUrl
,并附加以下文件名以获取其对应的文件:
hls
:source.m3u8
(包含对实际传输流文件的进一步引用,这些文件也可在此baseUrl
中找到,但您可能不想处理它)thumbnail
:source.png
,如果data.Has720pPreview
属性是true
,也是720p.jpg
raw
:source.mp4
(这是网站上提供给您的文件,作为您自己频道的下载选项,或者在所有频道上为具有 [=47= 的用户提供的下载选项) ]、Founder
或Guardian
个角色)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>