項目已開源到 GitHub,項目地址:HiMeditator/auto-captionhttps://github.com/HiMeditator/auto-caption
軟件下載(Windows平臺):Releases · HiMeditator/auto-captionhttps://github.com/HiMeditator/auto-caption/releases
你是否遇到過看外語視頻卻沒有字幕的情況,或者環境嘈雜需要實時字幕來獲取信息。這時候一個能實時將系統音頻轉換為字幕和翻譯并顯示的軟件就能派上用場了。下面就介紹一下我最近開發的一個實時字幕軟件。
項目簡介

Auto Caption 是一個跨平臺的字幕顯示軟件,能夠實時獲取系統音頻輸入(錄音)或輸出(播放聲音)的流式數據,并調用音頻轉文字的模型生成對應音頻的字幕。軟件提供的默認字幕引擎(使用阿里云 Gummy 模型)支持九種語言(中英日韓德法俄西意)的識別與翻譯。目前軟件提供的自帶字幕引擎使用了阿里云的模型服務,所以要使用該字幕引擎需要獲取阿里云的 API KEY。
目前軟件默認字幕引擎只有在 Windows 平臺下才擁有完整功能。在 Linux 平臺下只能生成音頻輸入(麥克風)的字幕,還不支持音頻輸出(播放聲音)的字幕生成。
我還為項目制作了一個視頻,想了解項目的同學可以去看看:
開源字幕軟件Auto Caption:項目介紹與展示,捕捉音頻秒變文字,打造你的專屬字幕系統https://www.bilibili.com/video/BV1DCKiznENJ
整個項目可以分為四個部分:前端、后端、客戶端集成和字幕引擎。

前端開發
通過 Electron 框架,可以使用 Web 前端開發的技術棧來開發桌面軟件。我使用 Vue3 來開發該軟件的用戶界面,這部分開發和 Web 前端開發差不多,唯一不同的就是用 IPC 和后端通信。這部分 Electron 提供了很好的封裝,直接調方法就可以了。
前端的主要功能就是提供字幕引擎和字幕樣式的管理界面、提供字幕記錄的展示,以及提供另一個實時字幕顯示的窗口。

另一個問題就是該軟件需要兩個不同的窗口,那前端是否要為兩個窗口分別寫各種的前端項目呢?我使用路由(Vue Router)來載入不同的窗口,這樣就只需要一個前端項目就可以表示兩個窗口。需要注意的是,打開的兩個窗口處于不同的運行環境,因此它們的數據是不互通的,需要通過后端來交換數據。
后端開發
后端使用 Node.js 開發,主要用于管理字幕引擎和字幕樣式的設置以及字幕記錄。要實現系統音頻的實時獲取和字幕生成,使用 Node.js 會非常難實現,所以我把那部分剝離了出去,使用其他技術進行單獨開發,那部分也被稱為字幕引擎。因此后端還需要實現字幕引擎的調用,我使用的是?child_process 模塊下的 spawn 方法來調用字幕引擎。?
客戶端集成
項目使用 Electron 框架開發。Electron 是一個用于構建跨平臺桌面應用程序的開源框架。它結合了 Chromium 渲染引擎和 Node.js 運行時環境,允許開發者使用前端技術 + Node.js 來創建原生的應用程序。而且通過Electron,可以一次性編寫代碼,然后在多個操作系統上運行,包括Windows、macOS和Linux。
選擇 Electron 開發的原因主要就是對我來說學習成本較小,因為我之前主要在做前端開發和 VS Code 插件開發,對前端和 Node.js 都有了解,學習使用 Electron 開發桌面軟件就能很快入門。Electron 開發的缺點是每個應用都得打包自己的 Chromium 和 Node.js 副本,因此開發的桌面軟件占用空間較大,不太適合開發小工具。
項目開發使用了 Electron Vite 作為構建工具,通過 Electron Vite 可以快速生成初始項目模板,主進程和渲染進行的通信接口也進行了很好的封裝。Electron Vite 提供的便捷可以讓我更專注于項目的開發而不是環境的配置。
字幕引擎開發
所謂的字幕引擎實際上是一個子程序,它會實時獲取系統音頻輸入(錄音)或輸出(播放聲音)的流式數據,并調用音頻轉文字的模型生成對應音頻的字幕。生成的字幕轉換為 JSON 格式的字符串數據,并通過 IPC 傳遞給主程序。主程序讀取字幕引擎的數據,處理后顯示在窗口上。
字幕引擎的設計是模塊化的,因此如果了解了字幕引擎的工作原理和數據傳遞規范,其他開發者也可以開發自定義的字幕引擎。字幕引擎部分我寫了一個文檔介紹其工作原理和數據規范,感興趣的開發者可以去看看,在項目 GitHub 倉庫的 assets 文件夾下。

下面說說我自己開發的字幕引擎。要開發字幕引擎,首先就是系統音頻數據流的獲取。要獲取麥克風的輸入音頻比較容易,很多語言都有對應的庫。但是要獲取系統音頻的輸出流就比較麻煩了,這部分我查了很多資料,沒有找到合適的跨平臺解決方案。
最后我找到了一個適合 Windows 的 Python 庫 PyAudioWPatch,這個庫允許使用 WASAPI 設備作為環回使用 PyAudio。PyAudio 是 Python 中一個跨平臺的音頻庫,可以獲取系統錄音。而 PyAudio 使得在 Windows 平臺獲取系統音頻輸出也成為了可能。在 Linux 平臺我還沒有找到類似的庫,加上我現在配置的 Linux 虛擬機在開發字幕引擎時遇到了問題,因此該項目的字幕引擎在 Linux 上功能還不完整。

獲取到系統音頻流后還可能需要對系統音頻流進行處理。我使用的阿里云 Gummy 模型只能識別單通道的音頻流,但我獲取的是雙通道的音頻流。因此剛開始模型輸出的全是和原文不相關毫無邏輯的內容,后面摸索了很久我才發現問題。我使用了 NumPy 庫來進行音頻流的通道數轉換。代碼如下:
def mergeStreamChannels(data, channels):"""將當前多通道流數據合并為單通道流數據Args:data: 多通道數據channels: 通道數Returns:mono_data_bytes: 單通道數據"""# (length * channels,)data_np = np.frombuffer(data, dtype=np.int16)# (length, channels)data_np_r = data_np.reshape(-1, channels)# (length,)mono_data = np.mean(data_np_r.astype(np.float32), axis=1)mono_data = mono_data.astype(np.int16)mono_data_bytes = mono_data.tobytes()return mono_data_bytes
另一個問題是每次讀取的數據塊的大小。所謂的音頻流事實上是一個個被切分成的音頻數據塊。切分的音頻塊不宜過大或過小,經過我的嘗試,我編寫的字幕引擎將音頻塊切分為 50ms 每塊,識別效果比較好。
得到了處理好的音頻流后就是模型調用了,這部分參考使用的模型的接口文檔即可。在編寫完整的字幕引擎前可以先在 Jupyter Notebook 中編寫一個簡單的原型,確保方案可行。最后將模型返回的字幕和翻譯結果按接口規范,包裝為 JSON 格式的字符串,通過 IPC 傳遞給調用程序。
開發的 Python 程序通過命令行參數獲取字幕配置,在我的程序有三個命令行參數,分別表示:源語言、翻譯語言、音頻類型(如下圖)。開發完成后,使用 PyInstaller 將該 Python 程序打包為可執行文件,確保在不同用戶電腦上都可直接運行,這樣一個字幕引擎就做好了。

后續計劃
這個項目目前初步具有了實用價值,但是還有很大的改進空間。目前的改進計劃如下:
- 添加更多自帶字幕引擎。目前的字幕引擎只有 Gummy,而要使用該引擎需要申請阿里云百煉平臺的API KEY,對于普通用戶來說比較麻煩。之后考慮添加更多方便使用的字幕引擎,尤其是可以直接本地部署的模型。
- 添加多語言支持。目前軟件只支持中文,可以考慮添加英語和日語支持。
- 添加暗色主題,對于習慣使用暗色主題的用戶友好。
- 優化頁面樣式。