Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@hyrious/blivec

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hyrious/blivec - npm Package Compare versions

Comparing version 0.2.0 to 0.2.1

92

./dist/index.js

@@ -101,4 +101,4 @@ "use strict";

}
_on_error(err2) {
(this.events.error || noop)(err2);
_on_error(err) {
(this.events.error || noop)(err);
}

@@ -206,30 +206,66 @@ _on_data(buffer) {

}
export const FAIL = -1;
export const ENOENT = -60004;
async function getRealRoomId(id) {
const v1 = "https://api.live.bilibili.com/room/v1/room/room_init";
const ret = await get(`${v1}?id=${id}`);
const { code, data } = JSON.parse(ret);
if (code == 60004)
return ENOENT;
if (code == 0 && data.live_status == 1)
return data.room_id;
return FAIL;
}
function ok(data) {
return { ok: true, data };
}
function err(reason) {
return { ok: false, reason };
}
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
export async function getRoomPlayInfo(id) {
const roomId = await getRealRoomId(id);
if (roomId < 0)
return err(roomId === ENOENT ? "not found such room" : "failed");
const url = `${api_index_v2}/getRoomPlayInfo?room_id=${roomId}&platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
const { code, message, data } = JSON.parse(await get(url));
let code, message, data;
const room_v1 = "https://api.live.bilibili.com/room/v1/room";
const room_init = `${room_v1}/room_init`;
({ code, message, data } = JSON.parse(await get(`${room_init}?id=${id}`)));
if (code != 0)
return err(message);
return ok(data);
throw new Error(message);
const { uid, room_id, live_status, is_locked, encrypted } = data;
if (is_locked)
throw new Error("room is locked");
if (encrypted)
throw new Error("room is encrypted");
if (live_status !== 1)
throw new Error("room is offline");
const status = `${room_v1}/get_status_info_by_uids`;
({ code, message, data } = JSON.parse(await get(`${status}?uids[]=${uid}`)));
if (code != 0)
throw new Error(message);
const title = data[uid].title + " - " + data[uid].uname;
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
const streams = {};
const queue_of_qn = [1];
const visited = /* @__PURE__ */ new Set();
while (queue_of_qn.length > 0) {
const qn = queue_of_qn.shift();
if (visited.has(qn))
continue;
visited.add(qn);
const url = `${api_index_v2}/getRoomPlayInfo?room_id=${room_id}&qn=${qn}&platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
({ code, message, data } = JSON.parse(await get(url)));
if (code != 0)
throw new Error(message);
const { g_qn_desc, stream } = data.playurl_info.playurl;
const qn_desc = Object.fromEntries(g_qn_desc.map((e) => [e.qn, e.desc]));
let desc, container;
for (const { protocol_name, format } of stream) {
for (const { format_name, codec } of format) {
for (const e of codec) {
queue_of_qn.push(...e.accept_qn);
desc = qn_desc[e.current_qn];
if (protocol_name.includes("http_hls")) {
container = "m3u8";
desc += "-hls";
} else {
container = format_name;
}
if (e.codec_name === "hevc") {
desc += "-h265";
}
const { host, extra } = sample(e.url_info);
streams[desc] = {
container,
url: host + e.base_url + extra,
qn,
desc: qn_desc[e.current_qn]
};
}
}
}
}
function sample(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
return { title, streams };
}

@@ -6,7 +6,7 @@ #!/usr/bin/env node

import { Connection, getRoomPlayInfo, sendDanmaku } from "./index.js";
const [arg1, arg2] = process.argv.slice(2);
const [arg1, arg2, ...rest] = process.argv.slice(2);
if (arg1 === "get") {
const id = Number.parseInt(arg2);
if (Number.isSafeInteger(id) && id > 0) {
get(id);
get(id, ...rest);
} else {

@@ -24,5 +24,5 @@ help();

function help() {
console.log("Usage: bl <room_id> # listen danmaku");
console.log(" bl <room_id> <message> # send danmaku");
console.log(" bl get <room_id> # get stream url");
console.log("Usage: bl <room_id> # listen danmaku");
console.log(" bl <room_id> <message> # send danmaku");
console.log(" bl get <room_id> [--play] # get stream url");
process.exit(0);

@@ -88,15 +88,22 @@ }

}
async function get(id) {
const info = await getRoomPlayInfo(id);
if (!info.ok) {
console.log("Error:", info.reason);
async function get(id, ...args) {
let title;
let urls = [];
try {
const info = await getRoomPlayInfo(id);
title = info.title;
console.log(title);
console.log();
for (const name in info.streams) {
const stream = info.streams[name];
urls.push([stream.qn, stream.url]);
console.log(` ${name}: ${stream.url}`);
console.log();
}
} catch (err) {
console.log("Error:", err.message);
process.exit(1);
}
const platurl = info.data.playurl_info.playurl;
const codec = platurl.stream[0].format[0].codec[0];
const { base_url, url_info } = codec;
const { host, extra } = url_info[Math.random() * url_info.length | 0];
const url = host + base_url + extra;
console.log(url);
if (process.env.BLIVC_FFPLAY) {
if (args.includes("--play")) {
const url = args.includes("--max") ? urls.reduce((a, b) => a[0] > b[0] ? a : b)[1] : urls[0][1];
const headers = [

@@ -106,5 +113,14 @@ "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.1) Gecko/20100101 Firefox/60.1\r\n",

];
const args = [url, "-headers", headers.join(""), "-window_title", "a.flv"];
cp.spawnSync("ffplay", args, { stdio: "inherit" });
const cmds = [
"-hide_banner",
"-loglevel",
"error",
url,
"-headers",
headers.join(""),
"-window_title",
title
];
cp.spawnSync("ffplay", cmds, { stdio: "inherit" });
}
}

@@ -101,4 +101,4 @@ "use strict";

}
_on_error(err2) {
(this.events.error || noop)(err2);
_on_error(err) {
(this.events.error || noop)(err);
}

@@ -206,30 +206,66 @@ _on_data(buffer) {

}
export const FAIL = -1;
export const ENOENT = -60004;
async function getRealRoomId(id) {
const v1 = "https://api.live.bilibili.com/room/v1/room/room_init";
const ret = await get(`${v1}?id=${id}`);
const { code, data } = JSON.parse(ret);
if (code == 60004)
return ENOENT;
if (code == 0 && data.live_status == 1)
return data.room_id;
return FAIL;
}
function ok(data) {
return { ok: true, data };
}
function err(reason) {
return { ok: false, reason };
}
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
export async function getRoomPlayInfo(id) {
const roomId = await getRealRoomId(id);
if (roomId < 0)
return err(roomId === ENOENT ? "not found such room" : "failed");
const url = `${api_index_v2}/getRoomPlayInfo?room_id=${roomId}&platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
const { code, message, data } = JSON.parse(await get(url));
let code, message, data;
const room_v1 = "https://api.live.bilibili.com/room/v1/room";
const room_init = `${room_v1}/room_init`;
({ code, message, data } = JSON.parse(await get(`${room_init}?id=${id}`)));
if (code != 0)
return err(message);
return ok(data);
throw new Error(message);
const { uid, room_id, live_status, is_locked, encrypted } = data;
if (is_locked)
throw new Error("room is locked");
if (encrypted)
throw new Error("room is encrypted");
if (live_status !== 1)
throw new Error("room is offline");
const status = `${room_v1}/get_status_info_by_uids`;
({ code, message, data } = JSON.parse(await get(`${status}?uids[]=${uid}`)));
if (code != 0)
throw new Error(message);
const title = data[uid].title + " - " + data[uid].uname;
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
const streams = {};
const queue_of_qn = [1];
const visited = /* @__PURE__ */ new Set();
while (queue_of_qn.length > 0) {
const qn = queue_of_qn.shift();
if (visited.has(qn))
continue;
visited.add(qn);
const url = `${api_index_v2}/getRoomPlayInfo?room_id=${room_id}&qn=${qn}&platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
({ code, message, data } = JSON.parse(await get(url)));
if (code != 0)
throw new Error(message);
const { g_qn_desc, stream } = data.playurl_info.playurl;
const qn_desc = Object.fromEntries(g_qn_desc.map((e) => [e.qn, e.desc]));
let desc, container;
for (const { protocol_name, format } of stream) {
for (const { format_name, codec } of format) {
for (const e of codec) {
queue_of_qn.push(...e.accept_qn);
desc = qn_desc[e.current_qn];
if (protocol_name.includes("http_hls")) {
container = "m3u8";
desc += "-hls";
} else {
container = format_name;
}
if (e.codec_name === "hevc") {
desc += "-h265";
}
const { host, extra } = sample(e.url_info);
streams[desc] = {
container,
url: host + e.base_url + extra,
qn,
desc: qn_desc[e.current_qn]
};
}
}
}
}
function sample(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
return { title, streams };
}
{
"name": "@hyrious/blivec",
"version": "0.2.0",
"version": "0.2.1",
"description": "bilibili live cli",

@@ -5,0 +5,0 @@ "type": "module",

@@ -6,3 +6,3 @@ #!/usr/bin/env node

const [arg1, arg2] = process.argv.slice(2);
const [arg1, arg2, ...rest] = process.argv.slice(2);

@@ -12,3 +12,3 @@ if (arg1 === "get") {

if (Number.isSafeInteger(id) && id > 0) {
get(id);
get(id, ...rest);
} else {

@@ -27,5 +27,5 @@ help();

function help() {
console.log("Usage: bl <room_id> # listen danmaku");
console.log(" bl <room_id> <message> # send danmaku");
console.log(" bl get <room_id> # get stream url");
console.log("Usage: bl <room_id> # listen danmaku");
console.log(" bl <room_id> <message> # send danmaku");
console.log(" bl get <room_id> [--play] # get stream url");
process.exit(0);

@@ -101,18 +101,26 @@ }

async function get(id: number) {
const info = await getRoomPlayInfo(id);
if (!info.ok) {
console.log("Error:", info.reason);
async function get(id: number, ...args: string[]) {
let title: string;
let urls: [qn: number, url: string][] = [];
try {
const info = await getRoomPlayInfo(id);
title = info.title;
console.log(title);
console.log();
for (const name in info.streams) {
const stream = info.streams[name];
urls.push([stream.qn, stream.url]);
console.log(` ${name}: ${stream.url}`);
console.log();
}
} catch (err: any) {
console.log("Error:", err.message);
process.exit(1);
}
const platurl = info.data.playurl_info.playurl;
const codec = platurl.stream[0].format[0].codec[0];
const { base_url, url_info } = codec;
const { host, extra } = url_info[(Math.random() * url_info.length) | 0];
const url = host + base_url + extra;
console.log(url);
if (process.env.BLIVC_FFPLAY) {
if (args.includes("--play")) {
const url = args.includes("--max")
? urls.reduce((a, b) => (a[0] > b[0] ? a : b))[1]
: urls[0][1];
const headers = [

@@ -122,5 +130,14 @@ "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.1) Gecko/20100101 Firefox/60.1\r\n",

];
const args = [url, "-headers", headers.join(""), "-window_title", "a.flv"];
cp.spawnSync("ffplay", args, { stdio: "inherit" });
const cmds = [
"-hide_banner",
"-loglevel",
"error",
url,
"-headers",
headers.join(""),
"-window_title",
title,
];
cp.spawnSync("ffplay", cmds, { stdio: "inherit" });
}
}

@@ -277,38 +277,3 @@ import https from "https";

export const FAIL = -1;
export const ENOENT = -60004;
async function getRealRoomId(id: number) {
const v1 = "https://api.live.bilibili.com/room/v1/room/room_init";
const ret = await get(`${v1}?id=${id}`);
const { code, data } = JSON.parse(ret) as {
code: number | string;
data: Pick<RoomInfo, "room_id" | "live_status">;
};
if (code == 60004) return ENOENT;
if (code == 0 && data.live_status == 1) return data.room_id;
return FAIL;
}
interface Ok<T> {
ok: true;
data: T;
}
function ok<T>(data: T): Ok<T> {
return { ok: true, data };
}
interface Err {
ok: false;
reason: string;
}
function err(reason: string): Err {
return { ok: false, reason };
}
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
export interface RoomPlayInfo {
interface PlayUrlInfo {
playurl_info: {

@@ -319,2 +284,3 @@ playurl: {

stream: Array<{
protocol_name: string;
format: Array<{

@@ -339,17 +305,78 @@ format_name: string;

export async function getRoomPlayInfo(
id: number
): Promise<Ok<RoomPlayInfo> | Err> {
const roomId = await getRealRoomId(id);
if (roomId < 0)
return err(roomId === ENOENT ? "not found such room" : "failed");
interface PlayInfo {
container: string;
url: string;
qn: number;
desc: string;
}
const url =
`${api_index_v2}/getRoomPlayInfo?room_id=${roomId}&` +
`platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
export async function getRoomPlayInfo(id: number) {
let code: string | number, message: string, data: any;
const { code, message, data } = JSON.parse(await get(url));
if (code != 0) return err(message);
const room_v1 = "https://api.live.bilibili.com/room/v1/room";
const room_init = `${room_v1}/room_init`;
({ code, message, data } = JSON.parse(await get(`${room_init}?id=${id}`)));
if (code != 0) throw new Error(message);
return ok(data);
const { uid, room_id, live_status, is_locked, encrypted } = data;
if (is_locked) throw new Error("room is locked");
if (encrypted) throw new Error("room is encrypted");
if (live_status !== 1) throw new Error("room is offline");
const status = `${room_v1}/get_status_info_by_uids`;
({ code, message, data } = JSON.parse(await get(`${status}?uids[]=${uid}`)));
if (code != 0) throw new Error(message);
const title = data[uid].title + " - " + data[uid].uname;
const api_index_v2 = "https://api.live.bilibili.com/xlive/web-room/v2/index";
const streams: Record<string, PlayInfo> = {};
const queue_of_qn = [1];
const visited = new Set<number>();
while (queue_of_qn.length > 0) {
const qn = queue_of_qn.shift()!;
if (visited.has(qn)) continue;
visited.add(qn);
const url =
`${api_index_v2}/getRoomPlayInfo?room_id=${room_id}&qn=${qn}` +
`&platform=web&protocol=0,1&format=0,1,2&codec=0,1&ptype=8&dolby=5`;
({ code, message, data } = JSON.parse(await get(url)));
if (code != 0) throw new Error(message);
const { g_qn_desc, stream } = (data as PlayUrlInfo).playurl_info.playurl;
const qn_desc = Object.fromEntries(g_qn_desc.map((e) => [e.qn, e.desc]));
let desc: string, container: string;
for (const { protocol_name, format } of stream) {
for (const { format_name, codec } of format) {
for (const e of codec) {
queue_of_qn.push(...e.accept_qn);
desc = qn_desc[e.current_qn];
if (protocol_name.includes("http_hls")) {
container = "m3u8";
desc += "-hls";
} else {
container = format_name;
}
if (e.codec_name === "hevc") {
desc += "-h265";
}
const { host, extra } = sample(e.url_info);
streams[desc] = {
container,
url: host + e.base_url + extra,
qn,
desc: qn_desc[e.current_qn],
};
}
}
}
}
function sample<T>(arr: T[]): T {
return arr[Math.floor(Math.random() * arr.length)];
}
return { title, streams };
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc