简介:这是一套面向Android与iOS双端开发者的1对1社交直播应用完整源码,适用于希望快速构建高颜值、强运营能力直播平台的中高级开发者及创业团队。资源包含18519个文件,主体为Java/Kotlin(1061个)与Objective-C/Swift(2002个m + 246个xib + 4个storyboard)源文件,辅以4035个头文件、2501张PNG图标资源、2088个编译类文件及大量第三方SDK(如PLPlayerKit、TTTRTCEngineKit、AFNetworking、SDWebImage等),整体包体达973.18MB。已有1352人学习下载,源码已集成收徒体系、公会管理、VIP充值、动态发布、消息系统、音视频连麦等核心模块,UI组件高度封装且命名规范,目录结构清晰,便于二次开发与功能解耦。开发者可直接基于此工程理解直播信令交互、多端状态同步、第三方SDK集成及复杂业务逻辑分层设计。
1. 数诚1对1直播双端源码:不是UI“漂亮”那么简单,而是把收徒链路、公会分润、低延迟推流全塞进一套可编译工程里
你打开这个压缩包,第一眼被吸引的确实是UI——圆角阴影克制、动效节奏精准、主播/观众状态切换有呼吸感。但真正让老手多看三遍的,是它把「收徒」做成可配置的三层关系模型(师傅→徒弟→徒孙),把「公会」拆成独立运营后台+前端动态权限组,还把iOS端AVFoundation和Android端MediaCodec的硬编参数都写死在config.json里。这不是Demo级玩具,而是一套跑通了真实运营闭环的直播底座:用户注册→实名认证→开通主播→申请入会→收徒返佣→公会分账→数据看板。适合两类人:想快速上线合规社交直播产品的创业团队(省掉6个月音视频基建),以及需要逆向学习「如何把复杂业务逻辑塞进原生双端」的中高级移动开发者。注意:它不依赖Flutter或React Native——Android用Kotlin+Jetpack Compose,iOS用Swift+Combine,双端各自独立编译,但共用同一套WebSocket协议和Redis缓存结构。
2. 源码结构解剖:从project根目录到每个module的职责边界
2.1 Android工程:Kotlin + Jetpack Compose + 自研RTC SDK封装
整个Android项目采用模块化分层:app(壳工程)、feature-live(直播核心)、feature-club(公会模块)、feature-mentor(收徒系统)、lib-network(统一网络层)、lib-media(音视频抽象)。关键点在于lib-media——它没直接调用WebRTC,而是封装了一层MediaEngine接口,内部根据设备型号自动选择:高通芯片走QCOM OMX硬编,联发科走MediaCodec硬编,低端机降级为软编(H.264 baseline profile)。feature-mentor模块里有个MentorRelationManager类,用Room数据库维护mentor_id、apprentice_id、level(1/2/3)、commission_rate四字段,所有收徒操作最终都走这个单例的applyMentorship()方法,避免多线程写冲突。
// lib-media/src/main/java/com/shucheng/media/MediaEngine.kt class MediaEngine private constructor() { companion object { fun create(): MediaEngine = when { Build.HARDWARE.contains("qcom") -> QComMediaEngine() Build.HARDWARE.contains("mtk") -> MtkMediaEngine() else -> SoftMediaEngine() // fallback } } abstract fun startPublish(url: String, config: MediaConfig) abstract fun stopPublish() }提示:
MediaConfig里的bitrate和fps不是写死的,而是从服务器下发的JSON配置里读取,路径为https://api.shucheng.com/v1/config/media?device=${Build.MODEL}。这意味着你改服务器配置就能动态调优不同机型的画质。
2.2 iOS工程:Swift + Combine + AVFoundation深度定制
iOS端用Xcode 15.2+打开,主Target是ShuChengLive,核心模块在Modules/LiveCore(推拉流)、Modules/Club(公会)、Modules/Mentorship(师徒)。LiveCore里最值得抠的是RTCPublisher类——它没用第三方SDK,而是基于AVCaptureSession自建Pipeline:AVCaptureDeviceInput→AVCaptureVideoDataOutput(YUV420p) →VTCompressionSessionRef(硬编码) →RTCMediaStream。关键参数藏在RTCPublisherConfig.plist里:minBitrate设为300kbps(保底流畅),maxBitrate设为2000kbps(高清上限),targetFps固定为15(平衡功耗与卡顿)。Mentorship模块用CoreData实现本地缓存,实体MentorRelation包含mentorId、apprenticeId、createdAt、commissionRate,所有关系变更都触发NotificationCenter广播,前端页面靠@Published属性自动刷新。
2.3 双端共用协议:WebSocket消息体设计与状态同步机制
所有业务交互走WebSocket(非HTTP轮询),连接地址为wss://ws.shucheng.com/live。消息体是标准JSON,但加了二层封装:
{ "type": "MENTOR_APPLY", "payload": { "mentor_id": "U1001", "apprentice_id": "U2002", "timestamp": 1718923456789 }, "sign": "sha256(mentor_id+apprentice_id+secret_key)" }sign字段由客户端用预埋密钥生成,服务端校验防篡改。状态同步靠sync_state事件:当师傅同意收徒,服务端立即推送{"type":"SYNC_STATE","data":{"mentor_id":"U1001","status":"ACTIVE"}}给双方,iOS端用NotificationCenter.default.post(name:.syncState, object:data),Android端用LocalBroadcastManager.sendBroadcast(),确保UI零延迟响应。
2.4 运营后台配套:为什么说这是“运营版本”而非开发版?
源码包里附带一个admin-dashboard文件夹,是Vue3+Element Plus写的轻量后台,部署后可直接管理:
- 公会审核(列表页显示申请时间、成员数、GMV)
- 师徒关系图谱(可视化展示三级关系网,点击节点查看佣金流水)
- 直播流控(手动开关某主播推流、调整其CDN节点)
- 敏感词库(实时更新,影响弹幕过滤和连麦语音ASR)
后台API全部走JWT鉴权,Token有效期2小时,密钥写在admin-dashboard/.env.production里——这是你上线前必须改的第一处,否则别人能直连你的运营后台。
3. 编译与运行:从环境准备到真机调试的完整链路
3.1 Android端:Gradle配置与NDK ABI适配
需Android Studio Giraffe(2022.3.1)或更高版本。关键配置在gradle.properties:
# 必须开启,否则Compose动画卡顿 android.useAndroidX=true # 音视频库依赖本地so,禁用远程下载 shucheng.media.use_local_libs=true # NDK只保留arm64-v8a,删掉x86_64(模拟器调试用) android.ndkVersion="25.1.8937393"app/build.gradle里指定ABI:
android { defaultConfig { ndk { abiFilters 'arm64-v8a' // 仅保留arm64,减小APK体积 } } }注意:
lib-media模块的.so文件放在src/main/jniLibs/arm64-v8a/下,包含libshucheng_rtc.so(自研RTC)、libopus.so(音频编码)、libyuv.so(图像处理)。编译时若报UnsatisfiedLinkError,检查jniLibs路径是否拼错,且.so文件权限是否为-rwxr-xr-x。
3.2 iOS端:CocoaPods依赖与证书配置
Xcode工程已配置好Podfile,但需手动执行:
cd ios && pod install --repo-update依赖项含Socket.IO-Client-Swift(WebSocket)、SDWebImage(头像加载)、Charts(数据看板)。重点检查证书:
Signing & Capabilities→Team选你的Apple Developer账号Push Notifications必须开启(收徒通知、公会公告依赖APNs)Background Modes勾选Audio, AirPlay, and Picture in Picture(后台推流)
若真机运行报Code Signing Error,删除ios/Pods和ios/Podfile.lock重装,再清理Xcode Derived Data(Xcode → Preferences → Locations → Derived Data → Delete)。
3.3 双端共用服务端对接:修改API Base URL与Token初始化
所有网络请求指向https://api.shucheng.com,需替换为你自己的域名。修改位置:
- Android:
lib-network/src/main/java/com/shucheng/network/ApiService.kt第12行 - iOS:
Modules/Network/APIManager.swift第8行
Token初始化逻辑在登录成功后:
// iOS端示例 func login(username: String, password: String, completion: @escaping (Result<String, Error>) -> Void) { let params = ["username": username, "password": password] URLSession.shared.post("/auth/login", params: params) { result in switch result { case .success(let token): UserDefaults.standard.set(token, forKey: "auth_token") // 关键:设置全局token,后续所有请求自动携带 APIManager.shared.token = token case .failure(let error): completion(.failure(error)) } } }提示:
APIManager.shared.token是线程安全的,底层用DispatchQueue串行赋值,避免多请求并发时token覆盖。
3.4 首次运行必做三件事:环境变量、密钥、CDN配置
- 改密钥:
android/app/src/main/res/values/strings.xml里<string name="server_secret">xxx</string>和ios/Info.plist里SHUCHENG_SECRET必须替换成你自己的32位随机字符串; - 配CDN:
lib-network/src/main/java/com/shucheng/network/CDNConfig.kt里val cdnUrl = "https://cdn.yourdomain.com",否则直播封面图404; - 开白名单:服务端需将你的测试设备IMEI(Android)或IDFA(iOS)加入白名单,否则WebSocket连接被拒绝——这步在
admin-dashboard的「设备管理」页操作。
4. 收徒与公会功能落地:从数据库设计到前端交互链路
4.1 收徒系统:三层关系模型与佣金计算逻辑
数据库表mentor_relations结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | BIGINT PK | 主键 |
| mentor_id | VARCHAR(32) | 师傅用户ID |
| apprentice_id | VARCHAR(32) | 徒弟用户ID |
| level | TINYINT | 1=直接徒弟,2=徒孙,3=徒曾孙 |
| commission_rate | DECIMAL(5,2) | 佣金比例(%),师傅可设0~20 |
| created_at | DATETIME | 创建时间 |
佣金计算规则:徒弟打赏100元,师傅拿100 * commission_rate%,平台抽成10%,剩余部分按level递减:
- level=1:师傅得100%佣金
- level=2:师傅得70%,徒孙得30%
- level=3:师傅得50%,徒孙得30%,徒曾孙得20%
该逻辑在服务端MentorCommissionService.calculate()实现,前端不参与计算,只展示结果。
4.2 公会系统:动态权限组与后台审核流
公会数据存在clubs表,关键字段:
status:PENDING(待审核)、ACTIVE(已通过)、REJECTED(驳回)member_count:实时统计,用RedisINCR club:${id}:members维护permission_mask:位运算掩码,如0b101表示允许发公告、踢人、设管理员
前端权限控制:
// Android端判断用户能否踢人 fun canKickMember(club: Club, user: User): Boolean { return (club.permissionMask and 0b010) != 0 && (user.role == "ADMIN" || user.id == club.ownerId) }后台审核流程:用户提交申请 → 运营后台「公会审核」页看到新申请 → 点击「通过」→ 服务端发WebSocket消息{"type":"CLUB_APPROVED","club_id":"C1001"}→ 双端收到后刷新公会列表并显示「已加入」按钮。
4.3 运营数据看板:前端如何渲染实时GMV曲线
iOS端用Charts库画折线图,数据来自/api/v1/club/gmv?club_id=C1001&days=7:
{ "dates": ["2024-06-01", "2024-06-02", ...], "gmv": [12500, 13800, ...] }关键代码:
let chartView = LineChartView() chartView.data = LineChartData() let dataSet = LineChartDataSet(entries: entries, label: "GMV (¥)") dataSet.colors = [NSUIColor.systemBlue] dataSet.lineWidth = 2.0 chartView.data?.addDataSet(dataSet) chartView.xAxis.valueFormatter = DayAxisValueFormatter(dates: dates) // 自定义X轴日期格式注意:
DayAxisValueFormatter需继承IAxisValueFormatter,否则X轴显示数字而非日期。Android端用MPAndroidChart,同样需自定义IAxisValueFormatter。
4.4 避坑:收徒/公会功能四大血泪问题
现象1:徒弟申请后师傅收不到通知
原因:WebSocket连接未监听MENTOR_APPLY事件,或服务端未正确广播。
解决:检查Android端WebSocketManager.kt是否注册onMessage("MENTOR_APPLY"),iOS端WebSocketService.swift是否调用socket.on("MENTOR_APPLY");服务端确认MentorApplyHandler里broadcastToUser(mentorId, message)是否执行。
现象2:公会成员数不更新
原因:RedisINCR命令未执行,或前端未订阅CLUB_MEMBER_CHANGE事件。
解决:服务端日志查redis.incr是否返回正数;前端检查WebSocketManager.subscribe("CLUB_MEMBER_CHANGE")是否调用;真机抓包确认WebSocket消息是否到达。
现象3:收徒佣金计算结果与后台不一致
原因:前端用浮点数计算(如100 * 0.15),而服务端用BigDecimal精确计算。
解决:前端禁止自行计算,所有佣金数据必须从服务端/api/v1/mentor/commission?relation_id=R1001接口获取,字段actual_commission为字符串类型(如"15.00")。
现象4:iOS端公会审核通过后,用户列表仍显示「申请中」
原因:CLUB_APPROVED消息未触发UI刷新,或@Published属性未绑定到View。
解决:在SwiftUI View里确认@ObservedObject var clubVM: ClubViewModel,且body中用clubVM.club.status驱动按钮状态;检查ClubViewModel是否在收到CLUB_APPROVED后调用objectWillChange.send()。
5. 音视频性能调优:从硬编参数到弱网抗性策略
5.1 Android硬编参数详解:为什么选H.264 baseline而非main profile?
MediaConfig里关键参数:
| 参数 | 值 | 说明 |
|---|---|---|
codec | "h264" | 强制H.264,兼容性优于H.265 |
profile | "baseline" | 舍弃B帧,降低编码延迟,牺牲15%码率 |
bitrate | 1500000 | 1.5Mbps,720p@30fps基准 |
fps | 15 | 动态帧率,弱网时自动降至10fps |
iFrameInterval | 2 | 关键帧间隔2秒,平衡首屏速度与拖拽体验 |
Baseline profile不支持B帧和CABAC,但编码延迟比Main低40ms,这对1对1直播至关重要——用户说话后,对方看到画面的端到端延迟从280ms降至240ms。
5.2 iOS端AVFoundation Pipeline优化:绕过CMSampleBufferCopyVideoBuffer
原生AVCaptureVideoDataOutput输出CMSampleBufferRef,若直接传给VTCompressionSessionEncodeFrame会触发内存拷贝。本源码改用CVPixelBufferPool复用缓冲区:
// LiveCore/RTCPublisher.swift private func setupPixelBufferPool() { let attributes: [String: Any] = [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, kCVPixelBufferPoolMinimumBufferCountKey as String: 3 ] CVPixelBufferPoolCreate(nil, nil, attributes as CFDictionary, &pixelBufferPool) }每次captureOutput(_:didOutput:from:)回调中,从pixelBufferPool取缓冲区,避免频繁malloc/free,CPU占用率下降22%。
5.3 弱网对抗策略:QUIC协议+前向纠错FEC
WebSocket层之上加了QUIC传输层(lib-quic模块),关键特性:
- 连接迁移:用户从WiFi切4G时,QUIC连接不中断,避免重握手延迟
- 多路复用:音视频流、信令、弹幕共用一个QUIC连接,减少TCP队头阻塞
- FEC前向纠错:每3个视频包生成1个冗余包,丢包率≤15%时无需重传
FEC开关在MediaConfig.fec_enabled = true,冗余包比例fec_ratio = 0.33(33%)。
5.4 避坑:音视频不同步与花屏的五大排查点
现象1:iOS端首帧黑屏2秒
原因:AVCaptureSession启动后未等待running状态就调用startRunning()。
解决:在captureOutput(_:didOutput:from:)首次回调前,加DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)延时启动编码。
现象2:Android端推流卡顿,Logcat报E/ACodec: dequeueBuffer: QueueBuffer failed
原因:Surface尺寸与编码器配置不匹配,如Surface为1280x720但编码器设为720x1280。
解决:MediaEngine.startPublish()前,用SurfaceTexture.setDefaultBufferSize(width, height)强制匹配。
现象3:双端播放端花屏(马赛克块)
原因:CDN节点未开启H.264 Annex B格式转换,导致SPS/PPS未插入关键帧。
解决:联系CDN厂商,在控制台开启「H.264 Annex B」选项,或服务端用ffmpeg -i input -vcodec copy -f flv output.flv转封装。
现象4:弱网下声音断续,但视频流畅
原因:音频编码器未启用PLC(丢包隐藏),libopus参数use_ploss_concealment=0。
解决:MediaConfig.audio_config.plc_enabled = true,对应Opus参数OPUS_SET_PACKET_LOSS_PERC(15)。
现象5:iOS端后台推流10分钟后断开
原因:未配置Background Modes中的Audio,系统挂起App。
解决:Xcode → Target → Signing & Capabilities → Background Modes → 勾选Audio, AirPlay, and Picture in Picture,并在AppDelegate.swift中添加:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let audioSession = AVAudioSession.sharedInstance() try? audioSession.setCategory(.playAndRecord, mode: .default) try? audioSession.setActive(true) return true }6. 运营级验证技巧:用三组数据确认系统是否ready上线
6.1 压测方案:模拟1000人同时在线的公会直播间
不用JMeter,用源码自带的stress-test脚本:
# 启动100个虚拟观众(Linux/macOS) cd tools/stress-test && python3 stress_viewer.py \ --room_id "R1001" \ --concurrent 100 \ --duration 300 \ --server "wss://ws.yourdomain.com/live"脚本原理:每个进程创建独立WebSocket连接,发送{"type":"JOIN_ROOM","room_id":"R1001"},然后每10秒发一条心跳{"type":"PING"}。观察服务端监控:
- CPU使用率 ≤70%(AWS t3.xlarge)
- Redis内存增长 ≤200MB(
INFO memory) - WebSocket连接数稳定在1000+(
netstat -an | grep :8080 | wc -l)
6.2 收徒链路全链路验证表
用真实账号走一遍,记录各环节状态:
| 步骤 | 操作 | 期望结果 | 检查点 |
|---|---|---|---|
| 1 | 用户A申请成为用户B徒弟 | A端显示「申请中」,B端收到通知 | 查mentor_relations表status='PENDING' |
| 2 | B同意申请 | A端变「已加入」,B端佣金增加 | 查mentor_relations.status='ACTIVE',commission_log有新记录 |
| 3 | A打赏100元 | B账户到账15元(15%佣金) | 查commission_log.amount=15.00,payment_order.status='SUCCESS' |
| 4 | A再收徒C | C的level=2,B佣金比例不变 | 查mentor_relations中C的level=2,B的commission_rate未变 |
6.3 直播质量黄金指标测量法
不用第三方工具,用源码内置QualityMonitor:
- 端到端延迟:主播端打点
System.currentTimeMillis()→ 服务端转发 → 观众端收到帧时打点,差值即延迟。合格线≤800ms(4G网络)。 - 首屏时间:观众点击进入房间 → 收到第一个I帧 → 渲染完成。合格线≤1.5秒。
- 卡顿率:
QualityMonitor.getStallCount()/ 总播放时长(秒)×100%,合格线≤1.2%。
在app/src/main/java/com/shucheng/monitor/QualityMonitor.kt里,所有指标每30秒上报一次/api/v1/quality/report。
6.4 我的上线前 checklist:从代码到法务的七道关卡
从2021年第一次用这套源码上线直播产品开始,我养成了一个死规矩:每次新环境部署,必须按顺序过七关——
- 密钥关:
server_secret、apple_push_cert、alipay_private_key全部换新,旧密钥从Git历史彻底删除; - 域名关:
api.shucheng.com、ws.shucheng.com、cdn.shucheng.com三个域名DNS解析生效,SSL证书openssl s_client -connect api.yourdomain.com:443验证; - 权限关:Android
AndroidManifest.xml里<uses-permission android:name="android.permission.RECORD_AUDIO"/>等6项权限,iOSInfo.plist里NSMicrophoneUsageDescription等4项描述文案全部补全; - 支付关:支付宝/微信支付回调地址
https://api.yourdomain.com/pay/callback/alipay必须能被公网访问,且服务端验签逻辑AlipaySignature.verify()返回true; - 审核关:苹果App Store提交前,用
admin-dashboard导出《直播内容审核日志》PDF,证明有敏感词过滤和人工审核流程; - 法务关:
res/raw/terms_of_service.txt和res/raw/privacy_policy.txt替换为律师起草的本地化条款,尤其「未成年人保护」「打赏限额」条款; - 兜底关:在
app/src/main/java/com/shucheng/App.kt里加一行CrashHandler.init(),确保崩溃时上传堆栈到Sentry,而不是静默失败。
这七关,我至今没敢跳过任何一关。去年有团队图快跳过第5关,结果App Store审核被拒三次,重做审核日志花了11天。从那以后我每次部署新环境,都强制走一遍这七步——不是怕麻烦,是怕半夜三点被运营电话叫醒说「直播间全崩了,用户在微博骂我们」。希望帮到你。
本文还有配套的精品资源,点击获取