Write the Code. Change the World.

8月 04

即使如此,也只能在局域网使用。如果想广域网使用,还得拆分。将 srs 服务端部署到广域网,局域网拉取其他 rtmp 流,推送到服务端。广域网才能使用。 项目需要,还得将这个直播功能在其他广域网 web 中使用。

8月 04

现在更狠,要求服务端拉前端的流,还不告诉地址。还得让服务端通过前端广播的 udp 消息来确定拉流地址,然后进行推流处理。

修改后,代码结构如下:

pico rtmp 推流/
├── .env                          # 部署配置(Pico 地址 + CANDIDATE)
├── .gitignore                    ← 新增:忽略缓存/IDE/OS 残留
├── docker-compose.yaml           # srs + puller + controller 三服务
├── index.html                    # H5 播放页
├── srs.conf                      # SRS 配置
└── src/controller/
    ├── controller.py             # UDP 监听 + 健康检查 + 写共享地址
    ├── puller-wrapper.sh         # 监控地址变化、重启 ffmpeg
    ├── start-controller.ps1      # 原生启动脚本(备用)
    └── test-broadcast.py         # 广播模拟测试工具

继续阅读

8月 04

现在是客户端不推流到服务端,反而是服务端拉取客户端的流,再分发出去。

https://blog.vini123.com/1414

上边这个链接客户端推流模式,这个简单,实用。但有时候,却说推不了流,只能被动拉流。 这个会增加复杂度,使用范围变成了局域网。

开始

文件目录:

├── .env                 # 配置文件
├── srs.conf             # SRS 5.x:RTMP 接流 + HLS/HTTP-FLV/WebRTC 三协议输出
├── docker-compose.yaml  # 一键启动,CANDIDATE 环境变量注入 WebRTC 候选 IP
└── index.html           # H5 播放页:WebRTC 优先 → HLS 兜底,断线自动重试

继续阅读

8月 04

客户端向服务端推流,前端 h5 播放流。

https://ossrs.io/lts/zh-cn/

SRS(Simple Realtime Server)是一个简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。Oryx是一个一体化、开箱即用、开源的视频解决方案,可部署在云上或自建机房,以直播和WebRTC等能力赋能你的业务。

继续阅读

8月 03

php artisan tinker; 使用时,报错 Error Class "Psy\Readline\Interactive\Helper\TokenHelper" not found. 处理。

https://packagist.org/packages/psy/psysh

psy 版本:Psy Shell v0.12.24

root@a2129439b046:/www/tcrj.laravel# php artisan tinker;
Psy Shell v0.12.24 (PHP 8.5.5 — cli) by Justin Hileman
New PHP manual is available (latest: 3.1.1). Update with `doc --update-manual`

tinker 版本:

root@a2129439b046:/www/tcrj.laravel# composer show laravel/tinker
name : laravel/tinker
descrip. : Powerful REPL for the Laravel framework.
keywords : REPL, Tinker, laravel, psysh
versions : * v3.0.2
released : 2026-03-17, 4 months ago
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage :
source : [git] https://github.com/laravel/tinker.git 4faba77764bd33411735936acdf30446d058c78b
dist : [zip] https://api.github.com/repos/laravel/tinker/zipball/4faba77764bd33411735936acdf30446d058c78b 4faba77764bd33411735936acdf30446d058c78b
path : /www/tcrj.laravel/vendor/laravel/tinker
names : laravel/tinker

进入 vendor 中,确实没看到 TokenHelper 这个类。手动去官网复制一份下来。
https://github.com/bobthecow/psysh/blob/main/src/Readline/Interactive/Helper/TokenHelper.php

进入到 vendor 目录,创建 TokenHelper.php 文件,复制代码进去。

<?php

/*
 * This file is part of Psy Shell.
 *
 * (c) 2012-2026 Justin Hileman
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Psy\Readline\Interactive\Helper;

/**
 * Shared token analysis utilities.
 */
class TokenHelper
{
    /** @var int[] Token types that indicate a statement continues on the next line */
    private const TRAILING_TOKEN_OPS = [
        \T_OBJECT_OPERATOR, \T_PAAMAYIM_NEKUDOTAYIM,
        \T_BOOLEAN_AND, \T_BOOLEAN_OR, \T_LOGICAL_AND, \T_LOGICAL_OR,
        \T_DOUBLE_ARROW, \T_COALESCE, \T_SPACESHIP,
    ];

    /** @var string[] Single-character operators that indicate continuation */
    private const TRAILING_CHAR_OPS = ['+', '-', '*', '/', '%', '.', '=', '&', '|', '^', '<', '>', ','];

    /**
     * Check whether the last non-whitespace token is a trailing operator.
     *
     * Used to determine whether a statement continues onto the next line.
     *
     * @param array $tokens token_get_all tokens
     */
    public static function hasTrailingOperator(array $tokens): bool
    {
        if (empty($tokens)) {
            return false;
        }

        $lastToken = null;
        for ($i = \count($tokens) - 1; $i >= 0; $i--) {
            $token = $tokens[$i];
            if (\is_array($token) && $token[0] === \T_WHITESPACE) {
                continue;
            }

            $lastToken = $token;
            break;
        }

        if ($lastToken === null) {
            return false;
        }

        if (\is_array($lastToken)) {
            return \in_array($lastToken[0], self::TRAILING_TOKEN_OPS, true);
        }

        return \in_array($lastToken, self::TRAILING_CHAR_OPS, true);
    }
}

再重启 composer。

composer dump-autoload -o

再使用 tinker 就可以了。