Skip to content
TwhomeGHPublic

About

適用於iOS直播推流應用

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,983 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

松鼠🐿️推流

適用於iOS的直播推流應用

最近註冊了 愛發電有興趣可以去看看

愛發電 快樂大松鼠

主畫面

Warning

說明文件不即時 由於後續更新迭代多次

文檔可能沒有更新 所以實際包含功能會有所區別

更新紀錄

近期更新包含:

  • 擷取與錄影:新增 ScreenCaptureKit 擷取路徑,保留 ReplayKit;提供本地錄影、分段與壓縮設定。
  • 操作介面:整併主頁、設備資訊、日誌、音訊與設定五個分頁,改善平板布局。
  • 推流診斷:補強影音管線、RTMP 連線與時間戳日誌,方便追查推流問題。

各項功能的版本、限制與驗證進度,請參閱 完整變更歷史。

問題應對方案

如果你遇到一些奇怪的問題 可以先看Wiki頁
有些問題 已被發現記載在此

常見問題處理方式 - Common Problem Solutions

螢幕擷取與本地錄影

主頁可選擇擷取來源與工作模式。

擷取來源

  • ReplayKit:保留既有廣播擴展推流方式。
  • ScreenCaptureKit:需要 iOS/iPadOS 27 或更新版本,可使用推流與本地錄影功能。

兩種來源的設定支援程度可能不同,請依所選來源的介面提示操作。

本地錄影

使用 ScreenCaptureKit 時,可以選擇只錄影,先確認畫面、方向與聲音,再進行直播。

錄影相關功能包含:

  • 錄製品質與壓縮設定。
  • 畫面方向修正。
  • 分段錄製,以及結束後合併分段。
  • 從本地錄影清單查看檔案資訊,並進入碼率分析。

Note

分段錄製可保留已完成的段落,降低意外中斷造成整場錄影無法使用的風險

正在寫入的段落仍可能受影響。

影片碼率分析

從「設備資訊」右上角的碼率分析入口,可選取影片進行檢查。

  • 匯入影片:支援從相簿或「檔案」選取。
  • 查看資訊:檢查編碼格式、解析度、幀率與碼率。
  • 碼率圖表:觀察影片不同時間點的碼率變化,協助排查品質與檔案大小問題。

與本地錄影的關係

碼率分析用於檢查影片的編碼、尺寸、幀率及碼率,不會修改原始影片。

ScreenCaptureKit 本地錄影另有壓縮與分段設定

這些功能屬於錄影流程,並不代表此分析頁能替任意匯入影片進行壓縮或轉碼。

下載與安裝

手動下載 IPA

請前往 GitHub Releases,查看版本說明並下載對應的 IPA。

AltStore 來源

可透過 加入 AltStore 來源 開啟來源加入入口。

來源網址(固定,永遠指向最新 Release 上的來源檔): https://github.com/TwhomeGH/ReplyKit/releases/latest/download/AltStoreTest.json

AltStoreTest.json 是版控中的樣板,CI 不會改寫它。每次預設分支建置並發布 Release 時,CI 會用樣板加上實際的 downloadURL、size、version、buildVersion、date 合成一份,附在該 Release;version/buildVersion 取自封存後的 Info.plist,不由 tag 推測。版本的 What's New 取自該次建置最近 10 筆 commit,寫入 versions[].localizedDescription;App 層的 localizedDescription 仍是商店頁介紹。

Note

AltStore 是否提示更新仍取決於 version/buildVersion 是否改變;CI 只保證下載指向正確,不會自動遞增版本號。 第一次改用 Release asset 後,請等下一次 Release 產生 AltStoreTest.json;在那之前舊的 raw main 來源仍是唯一可用入口。 安裝後的連線與設定同步注意事項,請參閱下方「側載用戶說明」。

贊助支持

本專案為個人開發,致力於提供優質的直播推流應用。為了維持持續開發與更新,我們誠摯邀請您參與贊助支持。

贊助管道

目前支援以下贊助方式:

贊助用途

您的贊助將用於:

  • 維持開發與更新
  • 或支持其他項目開發
  • 提升技術研發能力
  • 開發新功能與改善體驗

感謝您的支持

感謝您對本專案的贊助,您的支持是我們持續開發的重要動力。

側載用戶說明

主 App 與 ReplayKit 廣播擴展需要交換設定、狀態與日誌。

當安裝環境無法使用 App Group 共享容器時,會依賴 Socket 通訊。

是否能使用 App Group,取決於簽章與權限配置,不能只由「側載」判定。

若使用 ReplayKit 時出現設定未套用或診斷資料未更新,請先確認:

  • 主 App 的 Socket 服務是否已啟動。
  • 廣播擴展是否已連上主 App。
  • 相關資料轉送與日誌選項是否已啟用。

排查時請一併提供 App 版本、擷取來源及日誌,方便確認是哪一段通訊未完成。

Socket 轉送

在「設定 → Socket 與連線」查看本機內網 IPv4 位址、服務端口與連線狀態。

  • 預設端口為 9322,可依需要修改。
  • 外部工具連線時,請使用主 App 顯示的位址與端口。
  • 若服務啟動失敗,請查看日誌中的錯誤原因,確認端口是否被占用。
  • 若無法連線,請確認裝置與外部工具的網路可互通,並檢查系統的區域網路權限。

Socket 服務與日誌轉送是不同設定

需要收集廣播擴展的日誌時,請另外確認相關轉送選項已啟用。

畫面方向檢查

首次使用或切換擷取來源後,建議先做短時間錄影或測試推流,確認畫面方向與比例。

若畫面側轉、上下顛倒或比例不符,請檢查目前擷取來源對應的方向修正與畫布設定。

ReplayKit 與 ScreenCaptureKit 的推流、本地錄影可能使用不同的處理路徑

請分別確認結果,避免重複旋轉。

TODO 待辦事項

集中管理於 TODO.md。

調試用設定

調試用設定 設定頁

GPU旋轉處理設定

GPU 旋轉設定 設定頁

為什麼需要旋轉處理?

擷取到的影像尺寸與方向資訊,可能與預期的播放方向不同。

當輸出畫面側轉或顛倒時,可透過方向修正調整。

旋轉與畫布尺寸應一起確認,避免畫面轉正後仍出現拉伸、裁切或黑邊。

可設定參數

  • 畫布輸出寬高:可自定義輸出畫面的寬度與高度
  • GPU處理寬高:可自定義GPU旋轉/縮放使用的中間處理寬高
  • 配置名稱:方便辨識用
  • 選擇方向:橫向直向
  • 只改輸出寬高[畫布本身]:開啟後GPU處理最終產物寬高與原始一致
  • 輸入緩衝區數量:太大會碰到擴展運存限制50MB 保持在3或5
  • 插值方式:使用 Bicubic 插值
    • 運算較慢,但保留細節更好
    • 對大動態畫面可減少模糊
    • 預設不使用 用線性即可

GPU/畫布分辨率

dstW/dstH 是 GPU 中間處理尺寸,odstW/odstH 是最終畫布與 encoder 輸出尺寸。 詳細設計與 preset 對照見 Docs/video-dimensions.md。

音訊設定

Audio

音訊相關功能分為

  • 音訊分頁:調整 App 與麥克風音量,查看最近回報的音量。
  • 設定 → 音訊處理設定:配置降噪、回音消除等處理選項。

降噪與回音消除

  • 降噪:降低背景噪音。

  • 回音消除:減少應用聲音經喇叭播放後,再被麥克風收錄的回音。

實際效果會受到收音環境、音訊路由與處理設定影響。

舊版 App 增益

Warning

舊版 App 增益已棄用,目前保留於進階選項,預計後續移除。

一般音量調整請使用「App 聲音」卡片中的音量控制。

日誌與問題排查

日誌主頁 日誌更多設定 日誌更多02

查看日誌

「日誌」分頁以主 App 的 log.txt 為歷史資料來源,可查看較早紀錄或回到最新日誌。

頁面提供來源篩選,方便區分主 App 與外部來源的紀錄。能否看到廣播擴展日誌,取決於擴展是否已連線,以及相關記錄與轉送設定。

日誌設定

從「設定 → 日誌設定」,或日誌頁內的設定入口,調整記錄與轉送選項。

排查特定問題時,可啟用對應的 RTMP、畫面處理或 PiP 診斷。提供紀錄時,請註明問題發生時間、擷取來源及操作步驟。

RTMP 時間軸診斷的啟用方式與欄位說明,請參閱 時間軸診斷文件。

外部日誌服務

需要將日誌送到自架服務時,可設定 POST 接收位址。一般使用不必配置此外部服務。

服務端範例:LogServer.js。

設備信息

DeviceInfo DeviceInfo2

該頁面可以快速查看設備的重要信息,包括:

螢幕資訊

  • 裝置原始屏幕寬高(points / pixels)
  • ReplayKit 開播後得到的系統輸出解析度(如 1920×1334)

CPU / GPU 資訊

  • CPU 使用率(App 當前使用率)
  • CPU 核心數
  • 處理器 / GPU 名稱(如 A14 / Apple M1 GPU)

運行內存 RAM

以 task_vm_info 的 phys_footprint 為主(Jetsam 真正採計的值),並拆解來源:

  • 總 RAM
  • App 實際佔用(footprint = internal + compressed)
    • internal:自身配置(heap / 緩衝)
    • compressed:被記憶體壓縮器壓縮的部分
  • external:檔案映射(框架 / 靜態庫 code),可被系統 evict,不在 footprint 內、不可與 footprint 相減
  • resident / 峰值(含可回收映射,僅供對照)
  • 可回收 reusable / 可清除 purgeable:系統能直接從 App 回收的量
  • 距 Jetsam 上限(os_proc_available_memory())
  • PIP 輸出影像池(估,3 × W×H×4)

只看 resident_size 會偏高(含可回收的檔案映射頁);判斷記憶體壓力請看「App 實際佔用」(phys_footprint)。external 大只代表靜態連結的媒體庫(libsrt / libdatachannel / HaishinKit)code 被映射,並非 App 資料。

儲存空間 Storage

  • 總容量顯示
  • 已使用容量
  • 可用(含可清除)
  • 空閒 實際可使用

磁盤 I/O

  • Page In 分頁輸入
  • Page Out 分頁取出
  • App Write 應用寫入

系統信息 System Info

  • 當前iOS版本
  • 設備持續運行總時間
  • 電量

網路 Network

  • 介面 是WiFI或流量
  • 上行速度/下行速度 (待實現)

設備管線與性能報告

  • MetricKit性能報告 由系統提供
  • 串流格式與RTMP傳輸
  • Video Pipeline 視頻管線 (由ReplyKit提供)
  • Audio Pipeline 音頻管線 (由ReplyKit提供)

PIP子母窗口聊天室

PIPChat子母聊天室

如何傳遞訊息給子母窗口

SocketApi服務端參閱以下:

Socket 傳輸說明

1. 連線資訊

  • 協議:TCP

  • 伺服器 IP / HOST:請填寫App端設備使用的地址

  • PORT:9322

2. 傳輸格式

每次發送的資料為 JSON 格式,並以換行符號 \n 作為結束符。

範例訊息

{
    "type": "StreamMessage",
    "user": "userName",
    "message": "message_text",
    "img": "https://img.icons8.com/?size=100&id=L8HgZUgz2jWS&format=png&color=000000",
    "giftImg": "https://img.icons8.com/?size=100&id=124077&format=png&color=000000",
    "isMain": true,
    "userNum": 1234,
    "userList": ["A", "B", "C"]
}

欄位說明

欄位 類型 說明
type String 消息類型,固定 "StreamMessage"
user String 使用者名稱
message String 訊息內容
img String 顯示用戶頭像用 使用圖示 URL
giftImg String 贈送禮物圖示 URL
isMain Boolean 是否為主要消息 (true/false)
userNum Number 可選參數,觀眾數;若有提供,會顯示在 PiP「直播中」標籤旁邊
userList Array<String> 可選參數,觀眾清單;目前會先接收保留,未提供也不影響既有功能

補充說明

  • userNum 與 userList 都是可選欄位,舊格式只傳 isMain 也能正常使用
  • 若 userNum 沒有傳入,PiP 不會額外顯示觀眾數標籤
  • userList 目前先保留給後續功能使用,現階段不會直接顯示在 PiP 畫面上

對子母畫面 發送直播開始/結束訊息

直播開始

{
    "type": "StreamStarting",
}
欄位 類型 說明
type String 接口消息類型

直播結束

{
    "type": "Ended",
    "Message":"StreamEnded"
}
欄位 類型 說明
type String 接口消息類型 Ended代表結束
Message String 顯示在子母用的結束訊息 使用預設填 StreamEnded

3. 發送方式(Python 範例)

import socket
import json
import time

HOST = "伺服器IP"
PORT = 9322

def create_connection():
    while True:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((HOST, PORT))
            print("Connected to server")
            return s
        except Exception as e:
            print("Connection failed, retrying in 3s...", e)
            time.sleep(3)

s = create_connection()

while True:
    message = {
        "type": "StreamMessage",
        "user": "user3333",
        "message": "Hello World",
        "img": "https://img.icons8.com/?size=100&id=L8HgZUgz2jWS&format=png&color=000000",
        "giftImg": "https://img.icons8.com/?size=100&id=124077&format=png&color=000000",
        "isMain": True,
        "userNum": 1234,
        "userList": ["A", "B", "C"]
    }

    try:
        s.sendall((json.dumps(message) + "\n").encode("utf-8"))
        print("Message sent")
    except BrokenPipeError:
        print("Broken pipe! Reconnecting...")
        s.close()
        s = create_connection()
        s.sendall((json.dumps(message) + "\n").encode("utf-8"))

    time.sleep(5)  # 每 5 秒發送一次
    

4. 長連線建議

為了提升訊息傳輸的穩定性和效率,建議使用 長連線模式:

  1. 保持連線活躍

    • 在建立連線後持續使用同一個 socket 發送多條訊息,避免每次發送都重新建立連線。

    • 適合頻繁推送資料的場景,例如直播聊天室、持續訊息流。

  2. 自動重連

    • 伺服器可能因超時或網路波動斷開連線,這時程式會捕獲 BrokenPipeError 自動重連,確保訊息不中斷。
  3. 範例程式特點

    • 使用 create_connection() 函數安全建立 TCP 連線。

    • 在無窮迴圈中發送訊息,每次發送前捕獲斷線錯誤。

    • 支援自動重連後繼續發送訊息。

  4. 其他建議

    • 長連線需要注意網路穩定性與錯誤處理,避免程式崩潰。
  5. 心跳訊息

    [!WARNING] 已移除/不再需要 — 此功能適用於 v11.4.2 之前(永久連線架構)的版本。 自 v11.4.2 起 Socket 改為按需連線(on-demand),連線短暫存活,不再需要心跳保活。 以下說明僅供仍使用舊版架構的參考。

    為了保持連線活躍,防止伺服器判定連線閒置而斷開,客戶端可以定期發送心跳訊息

    設計上是每60秒會清理一次 所以建議每30秒或在50秒時發一次維持

    • 發送內容:只需發送一個 JSON,type 設為 "heartbeat",並以 \n 結尾即可。

    • 伺服器行為:收到心跳訊息後會重置 idleTimer,確保連線不被自動關閉。

    欄位說明

    欄位 類型 說明
    type String 消息類型,固定 "heartbeat"

    Python 範例

    import socket
    import json
    import time
    
    HOST = "伺服器IP"
    PORT = 9322
    
    def create_connection():
        while True:
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((HOST, PORT))
                print("Connected to server")
                return s
            except Exception as e:
                print("Connection failed, retrying in 3s...", e)
                time.sleep(3)
    
    s = create_connection()
    
    while True:
        heartbeat = {
            "type": "heartbeat"
        }
    
        try:
            s.sendall((json.dumps(heartbeat) + "\n").encode("utf-8"))
            print("Heartbeat sent")
        except BrokenPipeError:
            print("Broken pipe! Reconnecting...")
            s.close()
            s = create_connection()
            s.sendall((json.dumps(heartbeat) + "\n").encode("utf-8"))
    
        time.sleep(30)  # 每 30 秒發送一次

背景記憶體管理

iOS 的 Jetsam 機制在記憶體緊張時會終止背景 App。本專案在進入背景時自動釋放非關鍵資源以降低被終止機率。

背景釋放項目 檔案 回收量
PiP 圖片快取 PIPContent.swift ~20MB
PiP pixel buffer pool PIPService.swift ~9MB
PiP render timer + pipeline PIPService.swift ~1MB
PiP 訊息圖層 PIPContent.swift ~2-5MB
LogModel 日誌緩衝 liveAPPApp.swift ~300KB
LogView 文字緩衝 ContentView.swift ~6-7MB

預期: 背景常駐記憶體從 ~90-100MB 降至 ~55-65MB,Jetsam 終止風險顯著降低。保留資源: SocketServer(log 管線)、PiP 渲染管線(若子母畫面 active)。詳見 Docs/replykit-core-fixes-summary.md §11。

About

適用於iOS直播推流應用

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages