Kyson - 音视频
type: channel
link: http://www.kyson.cn/index.php/category/音视频
items: libpag 源码解析
items: 拆包达人系列（1）：直播类应用 Jaco
items: SRS 部署小记
items: 出来鞭尸了！ijkplayer iOS 编译完全指南（Xcode 26.0.1 下，修复部分问题）
items: 一天入门 iOS 播放器
items: 一天内快速搭建直播服务器
items: FFmpeg源代码剖析
items: 入门视频看这一篇足够
items: 你想知道的B站弹幕细节都在这里

libpag 源码解析
type: item
date: 2025-12-16T16:11:00+08:00
description: 前言Jaco 中大量用到了 pag 动画，今天我们就来盘一盘 pag 的源代码。libpag 地址在这里。目录结构大概是这样： libpag/ ├── src/ # 核心源代码 ├── include/ # 公共 API 头文件 ├── third_party/ # 第三方依赖 ├── test/ # 测试代码和资源 ├── resources/ # 测试资源文件 ├── web/ # Web 平台实现 ├── ios/ # iOS 平台项目 ├── android/ # Android 平台项目 ├── mac/ # macOS 平台项目 ├── ohos/ # OpenHarmony 平台项目 ├── linux/ # Linux 平台支持 ├── win/ # Windows 平台项目 ├── viewer/ # PAG 查看器应用 ├── exporter/ # After Effects 导出器 ├── vendor/ # 供应商特定代码 ├── tgfx/ # TGFX 图形库（符号链接） ├── assets/ # 项目资源文件 └── .github/ # GitHub 配置 具体功能：src/base/作用: 基础数据结构和动画元素定义keyframes/: 关键帧动画系统，处理各种属性的时间插值 shapes/: 矢量形状定义（椭圆、矩形、路径、星形等） text/: 文本渲染相关（字体、段落、文字样式） effects/: 视觉效果（模糊、发光、阴影等 AE 效果） layerStyles/: 图层样式（描边、填充、渐变等） utils/: 基础工具类（数学运算、矩阵变换、颜色处理）src/codec/作用: PAG 文件格式编解码tags/: PAG 文件标签解析器，每个标签对应一种数据类型 mp4/: MP4 容器格式支持，用于视频预合成 utils/: 编解码工具（数据流读写、压缩解压）src/rendering/作用: 渲染引擎核心 layers/: 各种图层类型的渲染实现 ShapeLayer: 矢量形状图层 TextLayer: 文本图层 ImageLayer: 图片图层 SolidLayer: 纯色图层 PreComposeLayer: 预合成图层 filters/: GPU 滤镜和特效处理 video/: 视频解码和播放 sequences/: 序列帧管理 graphics/: 图形绘制基础设施 caches/: 渲染缓存系统（纹理、路径、字形缓存） drawables/: 可绘制对象抽象 editing/: 运行时编辑功能 renderers/: 不同渲染器实现 utils/: 渲染工具类 src/platform/作用: 平台特定实现android/: Android NDK/JNI 绑定，硬件解码器接口 ios/: iOS 框架集成，Metal/OpenGL 支持 mac/: macOS 特定功能，视频工具箱集成 cocoa/: iOS/macOS 共享的 Objective-C++ 代码 web/: WebAssembly 绑定，Canvas/WebGL 接口 win/: Windows 平台支持，DirectX/ANGLE 集成 ohos/: OpenHarmony 平台适配 linux/: Linux 平台基础支持 qt/: Qt 框架集成（跨平台 GUI） swiftshader/: 软件渲染器支持 源代码很难跑起来，我们要想使用他的话，还是下一个针对 iOS 的 demo。地址在这里：https://github.com/libpag/pag-ios开始iOS 项目一览运行 Demo 后，我们可以看到如下页面：可以看到他的功能比较强大，我们只需要一个 pag 文件，然后代码中加载即可。参考pag 官网

拆包达人系列（1）：直播类应用 Jaco
type: item
date: 2025-12-12T16:50:03+08:00
description: 前言从今天开始，我们出一个系列叫做拆包达人：通过对 IPA 包的拆解，逆向的方式来学习，废话不多说，现在开始。Jaco中东直播应用，对标 TikTok 或者抖音，其 APP 长这样：拆完 IPA 包后，我们看到目录如下：. ├── _CodeSignature │ └── CodeResources ├── ai_generating.pag ├── ai_preparing.pag ├── AliVideoCert-com_weo_projectz-20240418175247.crt ├── AppAuthCore_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── AppsFlyerLib_Privacy.bundle │ ├── Info.plist │ └── PrivacyInfo.xcprivacy ├── ar.lproj │ ├── AppLocalizable.strings │ ├── InfoPlist.strings │ ├── JacoLocalizable.strings │ ├── LaunchScreen.strings │ ├── LiveLocalizable.strings │ ├── Localizable.strings │ ├── Main.strings │ ├── MessageLocalizable.strings │ ├── RongCloudKit.strings │ └── RongSticker.strings ├── Assets.car ├── AVPlayerPage.txt ├── Base.lproj │ ├── LaunchScreen.storyboardc │ └── Main.storyboardc ├── batter_full_like.json ├── batter_like_avatar.json ├── batter_like_heart.json ├── batter_like_soccer.json ├── BeetoADBundle.bundle │ ├── Assets.car │ ├── Info.plist │ └── zh-cn.lproj ├── big_playback_lottie.json ├── big_record_lottie.json ├── BMeiSheSDK.bundle │ ├── Info.plist │ └── meishe.lic ├── box_open.json ├── box_unclick.json ├── box_win.json ├── Bubble Tea.png ├── caption.bundle │ ├── 0C1A0ABB-3ECA-46B3-95C4-07555BBA3A5F.1.captionstyle │ ├── 0C1A0ABB-3ECA-46B3-95C4-07555BBA3A5F.lic │ ├── 0D4D1A68-5CE2-46E8-8635-7672EBA35FA2.1.captionstyle │ ├── 0D4D1A68-5CE2-46E8-8635-7672EBA35FA2.lic │ ├── 1C7EE477-20E9-494F-BF48-4D37E834A725.1.captionstyle │ ├── 1C7EE477-20E9-494F-BF48-4D37E834A725.lic │ ├── 1E61C62D-1317-4A5C-8773-830A19514735.1.captionstyle │ ├── 1E61C62D-1317-4A5C-8773-830A19514735.lic │ ├── 2044EE5C-D0B6-4E76-B6D5-391F0C4AD05E.1.captionstyle │ ├── 2044EE5C-D0B6-4E76-B6D5-391F0C4AD05E.lic │ ├── 24206D2B-F06E-4AA5-B4DF-5E103DF9DAB7.1.captionstyle │ ├── 24206D2B-F06E-4AA5-B4DF-5E103DF9DAB7.lic │ ├── 2C7609BE-7563-4E79-853D-B5540F593A11.1.captionstyle │ ├── 2C7609BE-7563-4E79-853D-B5540F593A11.lic │ ├── 2FE34C0F-F984-456F-8E2F-60EB1FEFEB90.9.captionstyle │ ├── 2FE34C0F-F984-456F-8…

SRS 部署小记
type: item
date: 2025-12-06T22:28:00+08:00
description: 前言SRS 不用多介绍了，开干就行。一、安装 Docker# 安装 Docker sudo dnf install -y docker # 启动 Docker 服务 sudo systemctl start docker sudo systemctl enable docker # 验证安装 docker --version二、部署 SRS 流媒体服务器1. 拉取 SRS Docker 镜像docker pull ossrs/srs:52. 创建 SRS 配置文件mkdir -p /etc/srs cat > /etc/srs/srs.conf << 'EOF' listen 1935; max_connections 1000; daemon off; srs_log_tank console; http_server { enabled on; listen 8080; dir ./objs/nginx/html; } http_api { enabled on; listen 1985; } stats { network 0; } vhost __defaultVhost__ { # 直播优化配置 tcp_nodelay on; min_latency on; # 播放配置 play { gop_cache off; # 关闭 GOP 缓存，降低延迟 queue_length 10; # 播放队列长度 mw_latency 100; # 最小等待延迟 100ms } # HTTP-FLV 配置 http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } # HLS 配置（可选） hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 2; # 每个 TS 切片 2 秒 hls_window 10; # 保留 10 个切片 } } EOF3. 启动 SRS 容器docker run -d \ --name srs \ --restart always \ -p 1935:1935 \ -p 8080:8080 \ -p 1985:1985 \ -v /etc/srs/srs.conf:/usr/local/srs/conf/srs.conf \ ossrs/srs:54. 验证 SRS 运行状态# 查看容器日志 docker logs srs # 查看容器状态 docker ps | grep srs # 访问 Web 管理界面 # http://服务器IP:8080三、测试推流需要先安装 ffmpeg，没有的，来我这里看一下。1. 推流测试（彩条 + 实时时间）ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \ -f lavfi -i sine=frequency=1000:sample_rate=44100 \ -vf "drawtext=fontsize=60:fontcolor=white:box=1:boxcolor=black@0.7:x=(w-text_w)/2:y=(h-text_h)/2:text='%{localtime}'" \ -c:v libx264 -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -profile:v baseline -g 60 -b:v 800k \ -c:a aac -b:a 128k \ -f flv rtmp://127.0.0.1:1935/live/test2. 验证流状态# 检查流参数 ffprobe -v error -show_streams http://127.0.0.1:8080/live/test.flv # 应该看到： # codec_name=h264 # width=1280 # height=720 # pix_fmt=yuv420p3. 播放测试VLC 播放器：打开网络流：http://服务器IP:8080/live/test.flv

出来鞭尸了！ijkplayer iOS 编译完全指南（Xcode 26.0.1 下，修复部分问题）
type: item
date: 2025-12-02T16:26:00+08:00
description: 前言“GitHub 上的 ijkplayer 是‘尸体’，B站内部的 ijkplayer 是‘活体’。”那么，鞭尸有何帮助？老项目应该还有一些在维护，需要做一些适配的时候，我能提供一些帮助新人想上手直播拉流的，可以参考一下本文档。概述macOS 上为 iOS 平台如何编译 ijkplayer ？此文为您解答ijkplayer 是基于 FFmpeg 的轻量级 Android/iOS 视频播放器，具有以下特点：支持 iOS/Android 平台基于 FFmpeg n4.0 版本支持硬件加速解码支持直播流播放 (RTMP, HLS)可定制化的编解码器支持编译结果总览成功编译的架构 | 架构 | 目标平台 | SDK | 库文件大小 | 编译时间 | |-----|---------|-----|-----------|---------| | **arm64** | iOS 真机 | iPhoneOS | ~25 MB | ~8分钟 | | **x86_64** | iOS 模拟器 | iPhoneSimulator | ~31 MB | ~8分钟 | | **Universal** | 通用库 | 合并 | ~56 MB | ~1分钟 | 生成的库文件build/universal/lib/ ├── libavcodec.a (37.6 MB) - 编解码器核心库 ├── libavfilter.a (1.4 MB) - 音视频过滤器库 ├── libavformat.a (10.9 MB) - 封装格式处理库 ├── libavutil.a (3.0 MB) - 工具函数库 ├── libswresample.a (696 KB) - 音频重采样库 └── libswscale.a (4.3 MB) - 视频缩放库环境要求与配置系统要求macOS版本: 10.15+ (Catalina 或更高)Xcode版本: 14.0+ (本次使用 26.0.1)磁盘空间: 至少 5GB 可用空间内存: 建议 8GB+必需工具# 安装 Homebrew (如果未安装) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # 安装必需工具 brew install yasm # 汇编器 brew install pkg-config # 包配置工具 (可选) brew install nasm # 另一个汇编器 (可选) # 验证 Xcode 命令行工具 xcode-select --install xcode-select -p环境变量配置# 添加到 ~/.zshrc 或 ~/.bash_profile export PATH="/usr/local/bin:$PATH" export DEVELOPER_DIR=$(xcode-select -p)项目初始化与配置修改1. 克隆项目git clone https://github.com/bilibili/ijkplayer.git ijkplayer-ios cd ijkplayer-ios git checkout -B latest k0.8.82. 初始化 iOS 构建环境./init-ios.sh这个脚本会：下载 gas-preprocessor (ARM 汇编预处理器)拉取 FFmpeg 源代码为每个架构创建 FFmpeg 分支设置配置文件链接3. 关键配置修改3.1 架构配置 (compile-ffmpeg.sh)# 只使用现代架构 FF_ALL_ARCHS_MODERN="arm64 x86_64" FF_ALL_ARCHS=$FF_ALL_ARCHS_MODERN3.2 Xcode 26+ 兼容性修复 (tools/do-compile-ffmpeg.sh)移除废弃的 Bitcode 标志:# arm64 架构 elif [ "$FF_ARCH" = "arm64" ]; then FF_XCODE_BITCODE="" # 原来是 "-fembed-bitcode" # x86_64 架构 elif [ "$FF_ARCH" = "x86_64" ]; then FF_XCODE_BITCODE="" # 原来是 "-fembed-bitcode"更新最低 iOS 版本:# arm64 FF_XCRUN_OSVERSION="-miphoneos-version-min=12.0" # x86_64 FF_XCRUN_OSVERSION="-mios-simulator-version-min=12.0"添加编译器兼容性标志:FFMP…

一天入门 iOS 播放器
type: item
date: 2024-06-17T20:47:00+08:00
description: iOS的音视频框架有 AVKit 和 AVFoundation，他们的关系如图：可以看出，avkit 位于相对上层，使用起来也更加容易，我们先讲解 avkit。AVKit苹果官方文档在这里：https://developer.apple.com/documentation/avkit/playing-video-content-in-a-standard-user-interface架构+------------------------------------------------------------------+ | Application Layer | | (Your App / SwiftUI / UIKit) | | | | - Custom Video Player UI | | - Playback Controls, Seek Bar, Buffer Indicator | | - Business Logic (e.g., DRM, Analytics, Playlist) | +-------------------------------+----------------------------------+ | | Uses \/ +------------------------------------------------------------------+ | High-Level AV Frameworks | | (Built on top of AVFoundation) | | | | +----------------+ +------------------+ +--------------+ | | | AVKit | | ReplayKit | | Photos | | | | (AVPlayerView, | | (Screen/Video | | (PHImage | | | | AVRoutePicker)| | Recording) | | Manager) | | | +----------------+ +------------------+ +--------------+ | | | | * Provides ready-to-use UI components | | * Simplifies common media tasks | +-------------------------------+----------------------------------+ | | Built upon \/ +------------------------------------------------------------------+ | AVFoundation Core | | (The main multimedia framework on Apple platforms) | | | | +------------------------------------------------------------+ | | | AVPlayer / AVQueuePlayer | | | | - Controls playback timeline | | | +------------------------------------------------------------+ | | | | +------------------------------------------------------------+ | | | AVPlayerItem | | | | - Represents a single media asset (video/audio) | | | | - Manages loading, buffering, tracks, metadata | | | +------------------------------------------------------------+ | | | | +------------------------------------------------------------+ | | | AVAsset / AVURLAsset / AVComposition | | | | - Describes media structure (tracks, duration, format) | | | | - Does NOT load data until needed (lazy) | | | +-----------------------------------…

一天内快速搭建直播服务器
type: item
date: 2024-06-10T23:41:00+08:00
description: 关于 SRSSRS(Simple Realtime Server)是一个简单高效的实时视频服务器，支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。Oryx是一个一体化、开箱即用、开源的视频解决方案，可部署在云上或自建机房，以直播和WebRTC等能力赋能你的业务。B站视频教程SRS开源服务器CentOS 安装下载虚拟机上安装，CentOS 系统下载地址：https://www.centos.org/download/安装按提示安装即可，需要注意的是，不要选最小化，而是选择包含图形界面的开启网络右上角开启网络安装/运行 Docker根据文档 docker 官方文档 安装即可。主要是以下几个命令：#来自 kyson.cn ，转载请注明出处 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo systemctl start docker安装 SRS根据文档 https://github.com/ossrs/srs/tree/5.0release 安装即可。本人截止目前是 release5.0，因此下了这个版本的。主要是执行以下命令：#来自 kyson.cn ，转载请注明出处 docker run --rm -it -p 1935:1935 -p 1985:1985 -p 8080:8080 \ -p 8000:8000/udp -p 10080:10080/udp ossrs/srs:5安装成功后，我们打开网页浏览器，输入 localhost:8080 确认一下：推流可以用 ffmpeg 或者 obs 推流。使用 ffmpeg 推流我找了个文档https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/这个可行性比较好，官网的让人摸不着头脑。大概命令是以下几个：#来自 kyson.cn ，转载请注明出处 sudo yum install epel-release sudo yum localinstall --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm sudo yum install ffmpeg ffmpeg-devel使用 obs 推流先去 obs官网下载 obs，下载完成后运行可见如下界面点击来源下面的加号（➕），添加录屏或者媒体源，再点击右边的开始直播即可。查看效果

FFmpeg源代码剖析
type: item
date: 2024-06-05T11:23:00+08:00
description: 在之前的文章入门视频看这一篇足够 中我们提到了 FFmpeg，也使用了 FFmpeg 最基本的命令：ffmpeg -i somemoive.mp4。今天我们就通过源码的方式来剖析 FFmpeg 的运行机制。概览ffmpeg总共有 7 大库，分别是avdeviceavcodecavformatswresampleswscalepostprocavfilter加上他们的共同依赖avutil，就算是八大库吧。这几大库按需配置，为了减少体积，建议将不用的关闭掉，关闭的时候还要根据他们之间的依赖关系，这个依赖关系可以在源代码ffbuild/config.mak 中看出。下载/编译/运行（VSCode）git clonegit clone https://git.ffmpeg.org/ffmpeg.git ffmpeg 配置./configure --enable-debug=3 --disable-optimizations比如我只想编译 h264 的解码器和支持硬解，那么只需要如下即可,没有配置的都会关闭，只打开你所配置的。./configure --disable-everything --enable-decoder=h264 --enable-hwaccel=h264_dxva2其他参数–enable-shared 默认情况下编译的库是静态的，如果我们想编译动态的，那么就可以加上这个选项。makemake -j2执行这一步后会发现多了很多文件。其中，以 _g 结尾的就是可以调试的程序ffmpeg_gffplay_gffprobe_g编辑 launch.json 文件 { "version": "0.2.0", "configurations": [ { "type": "lldb", "request": "launch", "name": "Debug", "program": "${workspaceFolder}/ffmpeg_g", "args": [ "-i", "/Users/kyson.cn/Downloads/kyson.cn.mp4" ], "cwd": "${workspaceFolder}" } ] } 运行运行后打印出了如下信息：ffmpeg version N-115575-g4e120fbbbd Copyright (c) 2000-2024 the FFmpeg developers built with Apple clang version 15.0.0 (clang-1500.3.9.4) configuration: --enable-debug=3 --disable-optimizations libavutil 59. 21.100 / 59. 21.100 libavcodec 61. 6.100 / 61. 6.100 libavformat 61. 3.104 / 61. 3.104 libavdevice 61. 2.100 / 61. 2.100 libavfilter 10. 2.102 / 10. 2.102 libswscale 8. 2.100 / 8. 2.100 libswresample 5. 2.100 / 5. 2.100 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/kyson/Downloads/7365320336742599978.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 comment : vid:v12044gd0000cordva7og65qe9e89sqg aigc_info : {"aigc_label_type": 0} encoder : Lavf58.76.100 Duration: 00:01:12.91, start: 0.000000, bitrate: 948 kb/s Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 576x768 [SAR 1:1 DAR 3:4], 909 kb/s, 30 fps, 30 tbr, 15360 tbn (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0] Stream #0:1[0x2](und): Audio: aac (HE-AACv2) (mp4a / 0x613…

入门视频看这一篇足够
type: item
date: 2024-03-16T17:15:00+08:00
description: 封装视频是什么？你可能知道 MP4，他是视频常用模式，你可能也听说过 AVI，FLV 等等很多视频格式，但她们内部是怎么构成的，你又不完全清楚。这里先和大家分享下，我们知道的这些视频文件格式其实只是封装方式。视频文件内部包含了视频数据和音频数据，把他们通过某种方式封装起来，使得视频和音频数据同步就是封装要做的事情。工具视频播放涉及太多知识，泛泛而谈毫无意义，比如上一节，我说了封装，但你听了以后肯定还是摸不着头脑。但如果有个工具可以边学习边操作理解起来就容易的多，这里我选择 FFmpeg。当然，OpenCV，VLC 原理也都差不多，学习其中的任何一种即可举一反三。下载 FFmpeg直接官网下载即可：https://ffmpeg.org/，在 download 选项下，找到您对应平台的二进制文件即可。代码时间有了FFmpeg，我这边直接通过如下命令来表明，视频文件是通过封装视频数据和音频数据来实现的：./ffmpeg -i LRV_20230927_182949_01_029.mp4 ffmetadata FFMETADATAFILE Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'LRV_20230927_182949_01_029.mp4': Metadata: major_brand : avc1 minor_version : 0 compatible_brands: avc1isom creation_time : 2023-09-27T18:29:39.000000Z cycle : 16 gop : 16 Duration: 00:00:12.88, start: 0.000000, bitrate: 13071 kb/s Stream #0:0[0x1](eng): Video: h264 (Main) (avc1 / 0x31637661), yuvj420p(pc, bt709, progressive), 368x640 [SAR 1:1 DAR 23:40], 3948 kb/s, 24 fps, 24 tbr, 24k tbn (default) Metadata: creation_time : 2023-09-27T18:29:39.000000Z handler_name : Ambarella AVC vendor_id : [0][0][0][0] encoder : Ambarella AVC encoder Side data: displaymatrix: rotation of 90.00 degrees Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 192 kb/s (default) Metadata: creation_time : 2023-09-27T18:29:39.000000Z handler_name : Ambarella AAC vendor_id : [0][0][0][0]其中 Stream #0:0[0x1](eng): Video: 表示的就是视频流；Stream #0:1[0x2](eng): Audio:表示的就是音频流。小结FFmpeg 看起来很强大，能直接知道读出视频文件中的视频部分和音频部分，虽然 Stream #0:0[0x1](eng): Video: 和 Stream #0:1[0x2](eng): Audio: 这两行后面的内容我们暂时还不能读懂，但猜测是对视频数据和音频数据的参数的一些详细解读。帧帧（Frame）是视频的基本组成单元。视频是由一系列连续播放的静态图像（帧）组成的，通过快速连续播放这些帧，我们可以看到平滑的运动效果。通常，帧以每秒显示的帧数（FPS, Frames Per Second）来衡量。在视频编码中，帧不仅仅是简单的图像，还可以分为不同类型，它们在视频压缩和解码过程中起到不同的作用。视频编码中的帧通常分为三种主要类型：I帧（Intra-frame）、P帧（Predictive frame） 和 B帧（Bidirectional frame）。它们在编码时的压缩效率和解码复杂度不同。帧类型定义特点优缺点I 帧自我包含的完整帧独立解码，不依赖其他帧占用空间大，解码简单，通常用作关键帧P 帧预测帧，依赖前面的 I 帧或 P 帧只存储差异，压缩效率较高解码依赖于参考帧，压缩效率中等B 帧双向预测帧，依赖前后帧双向参考，压缩效率最高解码依赖前后帧，压缩效率最高，复杂度高关于 FFmpegFFmpeg 并不能直接操作音视频，而是操作 PCM 或者 YUV随之而来的问题：YUV…

你想知道的B站弹幕细节都在这里
type: item
date: 2022-12-29T16:09:00+08:00
description: 进入B站后笔者首先着手的就是哔哩哔哩国际版的弹幕重构。哔哩哔哩国际版内部简称蓝版，这是因为其主题色位蓝色，这么做的目的是为了和国内的粉版区分。其能在海外的 App Store上下载到，以下是 APP 的介绍页面：蓝版的代码最初是从粉版 fork 出来的，并且阉割了一些比较重的、不常用的功能。考虑到海外的网络情况和国内差的不是一点半点，因此本人(kyson.cn)在重构弹幕时还做了很大幅度的优化。这会在文章中慢慢分享给大家。引言首先给大家提个问题：如果让您设计一个弹幕，你会怎么着手去做这件事。这里我相信大家不约而同肯定会想到：github。我们先罗列一下 github 上 star 数较多的几个弹幕库：弹幕库名star 数地址BarrageRenderer2.2khttps://github.com/unash/BarrageRendererDanmakuFlameMaster9.5khttps://github.com/bilibili/DanmakuFlameMasterBarrageRendererBarrageRenderer 是个人开发者编写的，完成度还算挺高，可惜目前已经不维护了。查看 BarrageRenderer 代码可知，其关键逻辑还是更改 UIView 的 Frame：#pragma mark - update /// 每个刷新周期执行一次 - (void)update { [_dispatcher dispatchSprites]; // 分发精灵 for (BarrageSprite * sprite in _dispatcher.activeSprites) { [sprite updateWithTime:self.time]; } } #pragma mark - update - (void)updateWithTime:(NSTimeInterval)time { _valid = !self.forcedInvalid && [self validWithTime:time]; _view.frame = [self rectWithTime:time]; if ([_view respondsToSelector:@selector(updateWithTime:)]) { [_view updateWithTime:time]; } } DanmakuFlameMasterDanmakuFlameMaster 简称 DFM，开源的只有 Android 版本，是哔哩哔哩早期使用的弹幕引擎。由于本人不是专业的 Android 开发，因此我不做过多分析。本人(kyson.cn)在B站第一个任务就是负责将 DFM 下架，转而使用字幕/弹幕统一框架 Chronos。 关于 Chronos 我后面做详细介绍，这里先和大家报告一下 DFM 在 iOS 版本下的一些实现原理。由于 iOS 版本的 DFM 没有开源，我这里不能将具体代码贴出，但我会将其实现原理大致告诉大家。和 BarrageRenderer 有一些相似之处我怀疑 BarrageRenderer 作者是否在B站工作过，他的设计理念，甚至一些方法名都和 DFM 一模一样。不信你看：- (void)updateWithTime:(DFMTime)time { //此处省略一部分代码 }这是核心的更新弹幕位置的函数。其他的部分相似的还有命名：DFMClock，设计思想也有一部分类似，因此看懂 BarrageRenderer 代码对理解 DFM 有一定帮助DFM 不是基于 UIKit这是和 BarrageRenderer 差异最明显的地方。DFM 基于更底层的 Metal/OpenGL，使用哪个 Render 组件取决于手机型号是否支持。Chronos不管是 BarrageRenderer 还是 DFM 都有一定的局限性：他们很难在 iOS 和 Android 实现统一，最多保证理念一致，但实现需要依靠各自平台库支持。这个时候一个大一统的方案呼之欲出，他就说 Chronos。Chronos 脱胎于谷歌的 Khronos ， 在 B 站内部被封装成了 Framework，接受 TS 注入，所以内部应该是有个 JSC 容器。如此一来，我们只需要把 js 逻辑写好，其他部分交给 chronos 来绘制即可。Android 和 iOS 各自安装一份 Chronos 库文件相对来说就容易的多。架构chronos 有多层构成，业务层无需关注底层引擎，只需要写对应业务，实现业务和底层隔离，并且能跨平台。底层实现既然能解释运行 ts，那么肯定里面有 jsc。大概的底层实现如下：具体 API 有如下这些：我们来总结一下这份 API：+-----------------…