承接 hejunjie/bililive 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

hejunjie/bililive

Composer 安装命令:

composer require hejunjie/bililive

包简介

B站直播 WebSocket 连接的核心组件库,提供简洁的接口实现,包括登录、直播间信息流加密/解密、以及相关的关键方法。适合集成到需要对接 Bilibili 直播间的项目中(弹幕监控,礼物答谢、定时广告、关注感谢,自动回复)

README 文档

README

English | 简体中文

A core PHP library for Bilibili live streaming WebSocket connections, providing interfaces for login, room operations, and danmu (bullet chat) stream encryption/decryption. Paired with long-running process solutions like Workerman, you can quickly build live room applications such as danmu monitoring, gift acknowledgments, scheduled ads, and auto-replies.

PHP Version License

Warning

This project is for learning and communication purposes only. Commercial or illegal use is strictly prohibited.

Want a quick overview? The codebase has been parsed by Zread.

Features

  • Complete Bilibili QR code login flow with automatic cookie assembly
  • Common live room operations: room info, danmu sending, mute management, online rankings, VIP count, and more
  • WebSocket packet construction and parsing, with support for Brotli and Zlib encrypted data decryption
  • Cookie-free support for select APIs (e.g., fetching basic user info)
  • All methods are static — no instantiation required

Requirements

Installation

composer require hejunjie/bililive

Quick Start

A minimal login → room info → WebSocket connection flow:

<?php

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

API Reference

Login

Method Description
Login::getQrcode() Generate a login QR code
Login::checkQrcode() Poll the QR code scan status; returns cookie on success
Login::getUserInfo() Get basic info of the currently logged-in user

Live

Method Description
Live::getRealRoomId() Get the real room ID (resolves short room IDs)
Live::getRealRoomInfo() Get live room basic info
Live::getInitialWebSocketUrl() Get WebSocket connection details
Live::getUserBarrageMsg() Get the user's danmu sending permissions for a room
Live::sendMsg() Send a danmu message
Live::reportLiveHeartbeat() Send web live heartbeat (every 60 seconds)
Live::getOnlineGoldRank() Get the room's online ranking
Live::addSilentUser() Mute a user in the room
Live::getSilentUserList() Get the room's muted user list
Live::delSilentUser() Unmute a user in the room
Live::getVipNumbers() Get the number of VIP subscriptions (Guard)
Live::getStreamerInfo() Get user basic info
Live::getMasterInfo() Get basic info of a specified UID without cookie
Live::getUserInfo() Get user basic info (deprecated, use getStreamerInfo())

WebSocket

Method Description
WebSocket::buildAuthPayload() Build authentication packet
WebSocket::buildHeartbeatPayload() Build heartbeat packet
WebSocket::parseResponsePayload() Parse response packets (auto-handles Brotli/Zlib decryption)

Example: Danmu Monitor with Workerman

The following example demonstrates how to connect to a Bilibili live room using Workerman and listen for danmu messages, gifts, and follows. Implement your own business logic inside onMessageReceived.

<?php

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);
    }
}

Related Projects

Project Description
php-bilibili-danmu-core Core Bilibili interaction module (this project)
php-bilibili-danmu-docker One-click Docker deployment
php-bilibili-danmu Main application
vue-bilibili-danmu-admin Frontend: Admin dashboard
vue-bilibili-danmu-shop Frontend: Mobile points shop

Notes

  • Traditional PHP-FPM is not well-suited for persistent connections due to its request-response model. Use long-running process solutions such as Workerman or Swoole.
  • The ext-brotli extension is required to decrypt WebSocket packets. Without it, danmu messages cannot be parsed correctly.
  • Live::getUserInfo() is deprecated. Use Live::getStreamerInfo() instead.

hejunjie/bililive 适用场景与选型建议

hejunjie/bililive 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.61k 次下载、GitHub Stars 达 6, 最近一次更新时间为 2024 年 10 月 28 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「bilibili」 「danmu」 「bili-live」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 hejunjie/bililive 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 hejunjie/bililive 我们能提供哪些服务?
定制开发 / 二次开发

基于 hejunjie/bililive 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.61k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 6
  • 点击次数: 14
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 6
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-10-28