How kaisoapbox/WhisperJournal Works
与主流依赖云服务的语音转录工具(如Otter.ai, Google Recorder)不同,WhisperJournal的核心竞争优势在于其“绝对隐私”。它通过集成Whisper.cpp本地推理引擎,实现了所有转录工作的离线处理,完全杜绝了数据上传服务器的隐私风险。它是一个开源的、为注重隐私的个人用户设计的纯粹日记工具,而非一个商业协作或会议记录产品。
Overview
与主流依赖云服务的语音转录工具(如Otter.ai, Google Recorder)不同,WhisperJournal的核心竞争优势在于其“绝对隐私”。它通过集成Whisper.cpp本地推理引擎,实现了所有转录工作的离线处理,完全杜绝了数据上传服务器的隐私风险。它是一个开源的、为注重隐私的个人用户设计的纯粹日记工具,而非一个商业协作或会议记录产品。
一款将用户隐私放在首位的移动端语音日记应用,通过完全在设备本地进行语音转文字,确保用户的日记内容永不离开手机。
How It Works: End-to-End Flows
创建一篇新的语音日记
这是应用的核心用户旅程。用户从打开应用开始,通过简单的点击即可完成一段语音的录制。录音结束后,系统在后台无缝地进行一系列自动化处理:首先将音频优化为最适合AI识别的格式,并根据用户偏好进行降噪;接着,强大的本地AI引擎会将语音精准地转写为文字,期间用户能看到清晰的进度反馈;最后,系统会将录音文件和生成的文本稿安全地保存在用户指定的本地位置。整个过程无需联网,确保了用户的隐私安全,最终在日记列表中呈现出一个图文并茂的完整条目。
- 用户开始和结束一次语音录制
- 系统自动对音频进行标准化处理和可选的降噪
- 系统使用本地AI模型进行语音转文字,并提供实时进度
- 系统将最终的音频和文本文件保存到用户配置的存储目录
- 新创建的日记条目出现在日记列表中
回顾与管理已有日记
用户可以通过“日记”标签页方便地管理他们所有的语音记录。应用会自动扫描并聚合所有相关的音频和文本,以清晰的列表形式呈现。用户可以随时进入任一条目,一边阅读由AI生成的文字稿,一边回放当时录下的原始语音,进行沉浸式回顾。此外,对于不再需要的日记,用户可以从列表中直接、永久地删除,以释放空间并保护隐私。整个管理过程完全在本地进行,简单直观。
- 用户进入日记列表,系统自动扫描并展示所有日记条目
- 用户选择一篇日记,进入详情页查看文本并播放录音
- 用户在列表中删除一篇不需要的日记
自定义应用与转录设置
为了满足不同用户的个性化需求,应用提供了一个功能丰富的设置中心。用户可以根据自己对转录准确度和设备性能的考量,自由选择不同大小的AI模型。同时,他们可以精细地控制转录行为,例如设定目标语言,或启用自动翻译功能。对于Android用户,该流程还提供了强大的存储管理能力,允许他们将日记数据从默认的应用文件夹迁移到自己选择的任何外部目录,从而完全掌控自己的数据。所有设置都会被自动保存,确保下次使用时体验一致。
- 用户进入设置界面
- 用户更改转录模型、语言或翻译等选项
- (仅Android)用户选择一个新的外部文件夹来存储日记
- 系统自动持久化所有设置更改
Key Features
核心转录管线
这是产品的核心引擎,负责将用户的原始语音录音转化为结构化的文本日记。该模块的设计目标是实现一个从录音、音频优化、本地转录到最终持久化存储的完整、可靠且高效的自动化流程。它通过强制的音频预处理确保转录质量,并通过智能的配置选项(如自动语言检测、翻译开关)为用户提供灵活的转录体验。所有处理均在设备本地完成,是产品隐私承诺的技术基石。
- 音频录制与状态反馈 — 【设计策略】提供一个简单、明确的录音界面,让用户可以轻松开始和结束录音,并获得清晰的实时状态反馈。 【业务逻辑】 - Step 1: 用户点击录音按钮后,系统首先请求麦克风使用权限。 - Step 2: 权限获取成功后,应用状态切换为“录音中”,并启动一个每秒更新的计时器,向用户展示已录制的时长。 - Step 3: 用户点击停止按钮,录音结束,计时器停止,系统将原始录音文件保存至临时位置,准备进入下一步处理。
- 音频标准化与可选降噪 — 【用户价值】原始录音可能因设备差异或环境嘈杂而影响转录准确率。此功能旨在通过标准化处理和降噪来提升最终的文字识别效果。 【设计策略】采用一个强制的音频格式转换流程,并提供一个用户可控的降噪开关,以平衡处理速度和转录质量。 【业务逻辑】 - Step 1: 录音结束后,系统自动调用FFmpeg工具进行音频处理。 - Step 2: **(强制)格式标准化**:无论原始格式如何,所有音频均被转换为Whisper模型要求的标准格式:16kHz采样率、单声道、16位PCM编码的WAV文件。 - Step 3: **(可选)智能降噪**:如果用户在设置中开启了“降噪”选项,系统会在FFmpeg命令中加入一个音频滤波器(`afftdn`,nf=-25),用于抑制背景噪声。 - Step 4: 处理完成的WAV文件被保存到应用的文档目录中,等待转录。
- 本地转录引擎与智能选项 — 【用户价值】在完全离线的环境下,将语音转化为文字,并智能处理多语言场景,如自动检测语言或将非英语内容翻译成英文。 【设计策略】集成设备端AI推理引擎(Whisper.cpp),并根据用户设置和所选模型,动态构建转录任务的参数,实现灵活的转录策略。 【业务逻辑】 - Step 1: 系统调用本地的`whisper.rn`库,对上一步生成的WAV文件发起转录任务。 - Step 2: **确定转录语言**:如果用户选择的模型是英文专用版(文件名以`.en`结尾),则语言强制设为英语。否则,使用用户在设置中选择的语言(默认为“自动检测”)。 - Step 3: **确定是否翻译**:仅当以下三个条件**同时满足**时,才会启用“翻译成英文”功能: 1. 用户在设置中开启了“翻译”开关。 2. 用户选择的语言模式为“自动检测”。 3. 用户选择的不是英文专用模型。 - Step 4: 转录过程中,系统会实时回调进度(0-100%)和预计剩余时间(ETA),并在界面上更新进度条,为用户提供明确的等待预期。 - Step 5: 转录完成后,系统获取纯文本结果并去除首尾多余的空白。
- 本地模型管理与加载 — 【用户价值】允许用户根据对准确度和设备性能的权衡,选择不同的转录模型,并确保模型在本地可用,以实现离线工作流。 【设计策略】在需要时从公共源(Hugging Face)自动下载并缓存模型文件到本地。针对特定平台(iOS)利用系统级优化(CoreML)来提升性能。 【业务逻辑】 - Step 1: 当用户选择一个模型或应用首次启动时,系统检查本地模型文件(例如 `ggml-base.bin`)是否存在。 - Step 2: 如果文件不存在,系统会从固定的网络地址开始下载,并向UI报告下载进度。 - Step 3: **(iOS平台专属优化)**:如果是在iOS设备上,系统还会额外检查并下载一个CoreML优化过的编码器模型包(`.mlmodelc.zip`),下载后自动解压,以加速转录过程。 - Step 4: 当所有必需的模型文件都准备好后,系统初始化Whisper引擎,使其进入待命状态。
日记管理与回顾
该模块为用户提供了与已生成的日记条目进行交互的完整闭环。用户可以方便地浏览所有日记,查看单篇日记的详细内容,回放原始录音,以及删除不需要的条目。其核心设计在于通过文件名约定自动关联音频和文本,并能无缝适应两种不同的存储后端(应用私有目录或用户选择的外部目录),为用户提供一致、简洁的管理体验。
- 日记条目发现与聚合 — 【设计策略】通过扫描存储目录并依据文件名约定,自动将音频文件(`.wav`)和对应的文本文件(`.md`)聚合为单个日记条目,简化列表展示。 【业务逻辑】 - Step 1: 用户进入“日记”列表时,系统扫描用户配置的存储目录。 - Step 2: 系统会过滤掉非日记文件,如模型文件(`.bin`)、设置文件(`.json`)等。 - Step 3: 系统根据文件名主干(去除扩展名)进行分组。例如,`2023-10-27-10-30-00.wav` 和 `2023-10-27-10-30-00.md` 会被识别为同一条日记的两个部分。 - Step 4: 聚合后的日记条目按文件名(即创建时间)进行字母顺序排序,并展示在列表中。
- 日记查看与音频播放 — 【设计策略】提供一个沉浸式的日记详情页,用户可以同时阅读转录文本并控制原始音频的播放,方便对照和回顾。 【业务逻辑】 - Step 1: 用户点击列表中的某个条目,进入详情页。 - Step 2: 系统异步读取并展示对应的`.md`文件内容作为转录文本。 - Step 3: 系统加载对应的`.wav`音频文件,并提供一个播放器界面,包括播放/暂停按钮和进度条。 - Step 4: 播放器状态(播放中、暂停、缓冲)和进度会实时同步到UI。当音频播放到结尾时,再次点击播放会从头开始重播。
- 日记条目删除 — 【用户价值】用户可以彻底删除不再需要的日记,由于是本地删除,进一步确保了隐私。 【设计策略】提供一个直接的删除操作,一次性移除与该条目关联的所有文件(音频和文本),并保证操作的幂等性以避免因文件不存在而导致的程序崩溃。 【业务逻辑】 - Step 1: 用户在日记列表项上点击删除按钮。 - Step 2: 系统会同时发起对该条目对应的`.wav`文件和`.md`文件的删除请求。 - Step 3: 删除操作被设置为“幂等”(idempotent),意味着即使文件已经被删除或不存在,操作也不会报错。 - Step 4: 删除操作完成后,系统会自动刷新日记列表。 【权衡】该功能没有设计二次确认弹窗,操作是即时且不可逆的,优点是操作流畅,缺点是存在误删风险。
用户配置与控制
该模块赋予用户对应用核心功能的高度控制权,体现了产品的透明和可定制性。用户不仅可以调整转录的行为(如模型、语言),还能在Android平台上自由选择日记的存储位置。这套完整的设置系统让用户可以根据自己的需求,在转录准确度、设备性能和数据管理便利性之间做出个性化的权衡。
- 安卓存储位置选择 (SAF集成) — 【用户价值】让Android用户能够将他们的私密日记存储在应用沙盒之外的任意位置(如SD卡、用户指定的文件夹),从而完全掌控自己的数据,并方便备份或迁移。 【设计策略】利用Android的存储访问框架(SAF),提供一个标准的系统文件选择器让用户授权目录访问,并在应用层面抽象存储接口,以兼容内部存储和外部SAF存储两种模式。 【业务逻辑】 - Step 1: 在设置界面中,仅对Android用户显示“选择目录”按钮。 - Step 2: 用户点击后,应用调用系统级的目录选择器,等待用户授权一个文件夹。 - Step 3: 如果用户授权成功,应用会保存该目录的访问凭证(URI)。所有后续的文件操作(如保存录音、读取日记)都会通过这个凭证进行。 - Step 4: 为了方便用户,应用还提供一个“使用应用默认目录”的按钮,可以一键恢复到最私密的应用沙盒存储模式。 - Step 5: **(文件持久化逻辑)** 当存储位置被设置为SAF目录时,录音转录流程会发生变化: 1. 转录完成的`.wav`和`.md`文件首先会在应用内部临时生成。 2. 系统随后在用户选择的SAF目录中创建对应的同名文件。 3. 系统将内部临时文件的内容复制到SAF目录的文件中。 4. 复制成功后,内部的临时`.wav`文件会被删除,以避免存储空间冗余。
- 应用设置持久化 — 【设计策略】通过将所有用户设置集中保存在一个本地JSON文件中,确保用户的个性化配置(如所选模型、语言、存储位置等)在应用重启后依然生效。 【业务逻辑】 - Step 1: 应用启动时,会尝试从设备的私有存储空间读取一个名为 `settings.json` 的文件。 - Step 2: 如果文件存在,应用会解析其中的内容,并用它来初始化各项设置的状态。 - Step 3: 当用户在设置界面中更改任何选项(如切换模型、开关降噪)时,应用会立即将当前所有设置项的最新状态序列化为JSON格式,并覆盖写入到 `settings.json` 文件中。 【权衡】设置的保存是即时触发的,没有做延迟或合并处理。这确保了用户修改后能立即生效并持久化,但如果用户快速连续修改多项设置,可能会引发频繁的磁盘写入,对性能和设备寿命有轻微影响。
Core Technical Capabilities
完全离线的隐私保护转录管线
Problem: 如何在移动设备上实现高质量的语音转文字功能,同时100%保证用户录音这一高度敏感的数据不被上传到任何云端服务器,从而彻底解决用户的隐私顾虑?
Solution: 通过一套精心设计的纯本地处理链条来解决此问题: - Step 1: **本地AI引擎集成**:应用内嵌了`whisper.rn`库,它直接调用C++实现的`whisper.cpp`推理引擎,使得所有AI计算都在用户设备上运行。 - Step 2: **前端音频预处理**:利用`ffmpeg-kit`在转录前对音频进行标准化处理(重采样、转单声道),确保了输入给AI模型的数据质量和兼容性,这是提升准确率的关键一步。 - Step 3: **离线模型管理**:应用实现了模型的按需下载和本地缓存机制。一旦模型下载完成,后续所有的转录过程均无需网络连接。 - Step 4: **平台加速利用**:在iOS上,该方案能自动下载并利用苹果的CoreML框架进行模型加速,提升了在苹果设备上的运行效率。
Technologies: whisper.rn, whisper.cpp, ffmpeg-kit-react-native, Expo FileSystem
Boundaries & Risks: 转录性能和速度高度依赖于用户的手机硬件,低端设备在处理长录音或使用大模型时可能会非常缓慢或消耗大量电量。模型文件本身较大,会占用用户较多的存储空间。整个处理流程是线性的,中间任何一步失败都可能导致转录中断,且可能留下需要手动清理的临时文件。
用户可控的灵活安卓存储方案
Problem: 在Android系统上,如何打破应用“沙盒”限制,让用户可以自由选择日记文件的存储位置(如SD卡),从而方便用户自行备份、管理,或避免应用卸载导致数据丢失?
Solution: 通过抽象存储层和利用Android的存储访问框架(SAF)来实现: - Step 1: **抽象存储接口**:在应用内部设计了一个统一的文件目录接口,该接口不关心底层是应用的私有目录还是外部的SAF目录。 - Step 2: **动态API切换**:通过一个布尔标志位 (`saf: true/false`) 来记录当前使用的存储模式。应用中所有文件操作(读、写、列出目录)之前,都会检查此标志位。 - Step 3: **调用正确API**:如果标志位为`true`,则调用Expo提供的`StorageAccessFramework`系列API,这些API能够操作用户授权的任意目录。如果为`false`,则使用标准的`FileSystem` API操作应用的私有目录。这种方式对上层业务逻辑是透明的。
Technologies: Android Storage Access Framework (SAF), Expo FileSystem
Boundaries & Risks: 当前实现中,将音频文件写入SAF目录时,需要将整个文件以Base64编码的形式读入内存再写入,对于长达数十分钟的录音,这可能会在内存较小的设备上导致应用崩溃。此外,如果用户在系统设置中手动撤销了应用的目录访问权限,应用目前缺乏优雅的降级或错误提示机制,可能导致后续保存操作失败。
基于文件系统的原子化日记管理
Problem: 在没有数据库的情况下,如何仅通过文件系统操作来可靠地管理日记条目,确保音频和文本的配对关系,并实现稳定的增、删、查操作?
Solution: 通过一套基于文件名约定的管理逻辑实现: - Step 1: **统一命名约定**:所有新创建的日记,其音频(`.wav`)和文本(`.md`)文件都使用相同的、基于时间戳的主文件名(如 `YYYYMMDD-HH-MM-SS`)。 - Step 2: **动态聚合**:在展示日记列表时,系统实时扫描存储目录,通过算法将拥有相同主文件名的`.wav`和`.md`文件动态地聚合为一“条”日记。这避免了维护一个独立的索引文件,降低了状态不一致的风险。 - Step 3: **幂等删除**:删除操作会同时尝试删除配对的两个文件,并使用 `idempotent: true` 选项。这保证了即使其中一个文件已经不存在,删除操作也不会因报错而中断,增强了操作的鲁棒性。
Technologies: Expo FileSystem, JavaScript
Boundaries & Risks: 该方案强依赖于文件名约定。如果文件名中包含多个点 `.`,目前的分割逻辑可能会出错。此外,由于没有数据库的事务支持,如果在文件写入过程中(如录音转录后保存文件的步骤)应用崩溃,可能会产生只有`.wav`文件或只有`.md`文件的“孤儿”条目。