1. Go to this page and download the library: Download hejunjie/bililive library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
hejunjie / bililive example snippets
use Hejunjie\Bililive\Live;
use Hejunjie\Bililive\Login;
// 1. Get login QR code
$qrcode = Login::getQrcode();
// Generate a QR image from $qrcode['url'] and let the user scan it with the Bilibili app
// Poll the scan status
while (true) {
$result = Login::checkQrcode($qrcode['qrcode_key']);
if ($result['code'] == 0) {
$cookie = $result['cookie'];
break;
}
sleep(1);
}
// 2. Get the real room ID
$realRoomId = Live::getRealRoomId(12345, $cookie);
// 3. Get WebSocket connection details
$wsData = Live::getInitialWebSocketUrl($realRoomId, $cookie);
// $wsData['token'] // auth token
// $wsData['host'] // server host
// $wsData['wss_port'] // WSS port
namespace app\server;
use Hejunjie\Bililive;
use Workerman\Timer;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Protocols\Ws;
class Bilibili
{
private int $reconnectInterval = 5;
private string $cookie;
private int $roomId;
public function __construct()
{
$this->cookie = ''; // Cookie copied from browser, or obtained via Login QR flow
$this->roomId = ''; // Room ID
}
public function onWorkerStart()
{
$this->connectToWebSocket();
}
private function connectToWebSocket()
{
$realRoomId = Bililive\Live::getRealRoomId($this->roomId, $this->cookie);
$wsData = Bililive\Live::getInitialWebSocketUrl($realRoomId, $this->cookie);
$wsUrl = 'ws://' . $wsData['host'] . ':' . $wsData['wss_port'] . '/sub';
$token = $wsData['token'];
$con = new AsyncTcpConnection($wsUrl);
$this->setupConnection($con, $realRoomId, $token);
$con->connect();
}
private function setupConnection(AsyncTcpConnection $con, int $roomId, string $token)
{
$con->transport = 'ssl';
$con->headers = $this->buildHeaders();
$con->websocketType = Ws::BINARY_TYPE_ARRAYBUFFER;
$con->onConnect = function (AsyncTcpConnection $con) use ($roomId, $token) {
echo "Connected to WebSocket, room: " . $roomId . "\n";
// Send authentication packet
$con->send(Bililive\WebSocket::buildAuthPayload($roomId, $token, $this->cookie));
// WebSocket heartbeat every 30 seconds
Timer::add(30, function () use ($con) {
if ($con->getStatus() === AsyncTcpConnection::STATUS_ESTABLISHED) {
$con->send(Bililive\WebSocket::buildHeartbeatPayload());
}
});
// HTTP heartbeat every 60 seconds
Timer::add(60, function () use ($con, $roomId) {
if ($con->getStatus() === AsyncTcpConnection::STATUS_ESTABLISHED) {
Bililive\Live::reportLiveHeartbeat($roomId, $this->cookie);
}
});
};
$con->onMessage = function (AsyncTcpConnection $con, $data) {
$this->onMessageReceived($data);
};
$con->onClose = function () {
echo "Connection closed, reconnecting...\n";
$this->scheduleReconnect();
};
$con->onError = function ($connection, $code, $msg) {
echo "Connection error: $msg (code: $code)\n";
$this->scheduleReconnect();
};
}
private function buildHeaders(): array
{
return [
"User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
"Origin" => "https://live.bilibili.com",
"Connection" => "Upgrade",
"Pragma" => "no-cache",
"Cache-Control" => "no-cache",
"Upgrade" => "websocket",
"Sec-WebSocket-Version" => "13",
"Accept-Encoding" => "gzip, deflate, br, zstd",
"Accept-Language" => "zh-CN,zh;q=0.9",
'Sec-WebSocket-Key' => base64_encode(random_bytes(16)),
"Sec-WebSocket-Extensions" => "permessage-deflate; client_max_window_bits",
'Cookie' => $this->cookie
];
}
private function onMessageReceived($data)
{
$message = Bililive\WebSocket::parseResponsePayload($data);
foreach ($message['payload'] as $payload) {
if (isset($payload['payload']['cmd'])) {
switch ($payload['payload']['cmd']) {
case 'DANMU_MSG': // Danmu message
// Implement your danmu handling logic here
break;
case 'SEND_GIFT': // Gift message
// Implement your gift acknowledgment logic here
break;
case 'INTERACT_WORD': // Follow notification
// Implement your follow acknowledgment logic here
break;
}
}
}
}
private function scheduleReconnect()
{
Timer::add($this->reconnectInterval, function () {
$this->onWorkerStart();
}, [], false);
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.