@kodykoala: Kody Video v2026.09.11 已发布。Kody Video 新改进已上线。
摘要
Kody Video v2026.09.11 已发布,新增针对移动端优先视频编辑的改进,包括增强的录制、时间线管理和导出功能。
查看缓存全文
缓存时间: 2026/09/12 17:00
Kody Video v2026.09.11 已发布。全新的 Kody Video 改进现已上线。https://t.co/Hau89GeIIn — # kentcdodds/kody-video 来源:https://github.com/kentcdodds/kody-video # Kody Video 移动优先的网页视频剪辑工具 相机:在预览区任意位置按住即可开始录制,将片段排列在胶片条时间轴上,然后点击 开始 导出/分享——所有操作均在设备端完成。Kody Video 灵感来源于 OK Video 的交互模型:以相机为核心进行捕捉,快速清理片段,以及一键完成确认/分享。这是一个独立的项目,拥有自己的名称、标识和实现;与 OK Video 无关,也不使用 OK Video 的商标或资源。树袋熊吉祥物由 KCD 社区 / kentcdodds.com/kody (https://kentcdodds.com/kody) 设计。应用内的 public/art/ 目录下的美术资源均由该 Kody 参考素材生成(相机、时间轴、分享、应用图标)。 ## 快速开始 bash npm install npm run dev 在 Chrome 浏览器(桌面或 Android)中打开控制台输出的 localhost 地址。相机/麦克风需要安全环境(http://localhost 或 HTTPS)。 bash npm run build # 生产环境构建 + 服务工作者 npm run preview # 服务 dist 目录(PWA 缓存已激活) npm test # 存储/导出规划器单元测试(Vitest 浏览器模式,真实 Chromium) npm run test:e2e # Playwright 端到端测试套件(模拟相机/麦克风;录制、编辑器、播放、导出、计划) npm run test:smoke # Playwright 用户体验冒烟测试(模拟相机,录制 + 导出) 在线应用: https://kody.video (Cloudflare Pages,从 main 分支构建)若需在局域网内手机访问,请使用本机局域网 HTTPS 地址,或使用隧道(npm run dev -- --host 加可信隧道)。在大多数浏览器中,纯 http:// 协议下 getUserMedia 将无法工作。 ## 功能一览 - 全屏实时相机预览(优先使用后置摄像头;若设备支持,可翻转、开启手电筒和变焦) - 在预览区任意位置按住录制;按住时上下拖动可进行变焦 - 自拍定时器,实现免手持拍摄(点击停止) - 录制状态反馈(录制提示胶囊 + 已用时间)——页面不会逐帧重新渲染,确保录制过程流畅 - 编辑器:胶片条时间轴(缩略图,宽度与片段时长成正比),拖动可重排、复制、删除并支持撤销,支持时间轴内拖动调整裁剪点,可从设备/相册添加片段和照片 - 时间轴上的照片:选中的图片将变成一个静态片段(默认 3 秒),在预览和导出时表现与其他片段相同——静音,其缩略图上有一个小相机标识。与裁剪条不同,照片会打开一个时长条:因为静态图像没有可供裁剪的媒体长度,其显示时长可自由增加或减少——拖动滑块在 0-30 秒范围内调节,点击预设时长(1/2/3/5/10 秒),或使用 ±0.5 秒的微调按钮精确设置,精确数值始终可见。照片在备份中与其他片段一样可复制/重排 - 逐片段音量调节:录制后,每个片段的音频都会进行峰值标准化(仅测量一次,保存在片段数据中,加载旧项目时会自动回填),因此不同距离录制的片段在预览和导出播放时音量保持一致。在时间轴上选中一个片段会显示片段音量滑块:调整该片段自身的音量(0-100%,默认 100%),可搭配音乐或不使用音乐 - 背景音乐(Plus 功能):创建一个音频轨道列表,按顺序在影片下方播放(不循环——当音乐在影片结束前播放完毕时,系统会提示添加下一首轨道)。每个轨道可独立设置音量(默认 25%——标准化的音乐会置于语音之下),并在轨道的详情视图中设置(类似片段裁剪视图的音频对应部分:裁剪轨道保留特定波形区间,设置音量,以及开启/关闭淡入淡出——默认开启;每个轨道在其开始处淡入,在结束处淡出,包括影片的开始和结束边缘)。选中的片段还可获得一个音乐滑块,用于在该片段播放期间压低背景音乐的音量(0-100%,默认 100%)——片段自身音量和音乐音量是两个独立控制,它们之间的混合是硬性限制而非耦合。音量变化会平滑跨越片段边界。所有这些——音量、标准化、淡入淡出、裁剪、轨道衔接——在预览和导出文件中的表现完全一致:项目预览会运行整部影片的背景音乐,编辑器的片段舞台则从时间轴上的精确位置开始播放音乐(预览中标准化提升会受浏览器音量上限限制) - 横屏项目(Plus 功能):无需设置——只需旋转手机。当项目尚无片段时,界面会根据设备握持方向调整,第一次录制会锁定方向(清空项目片段后,下一次首次录制会重新决定方向)。横屏模式会整体调整界面:手机形状的外壳会扩展至视口宽度,录制控件变为右侧栏,编辑器将播放器置于时间轴旁边,且当设备方向与锁定的项目不匹配时,系统会提示旋转。导出强制采用横屏项目方向(不匹配的片段会以中心裁剪方式处理),且锁定状态会保存在备份中。在免费方案中,旋转空项目会预览横屏界面,但执行锁定方向的录制会打开 Plus 升级提示。桌面端不受影响(网络摄像头和屏幕共享本身就是横屏媒体,无需选择):其项目保持未锁定状态,导出内容始终跟随片段,一如既往 - 项目预览播放:点击边缘可跳过片段,点击中间可暂停 - 最多 6 个稳定项目位槽(创建/打开/重命名/删除,海报图来自你的片段) - 大型“开始”行动号召:设备端导出至一个视频文件,然后分享(系统分享面板)或保存 - 备选方案:将片段保存为单独文件 - 项目备份/导入:每个项目对应一个 .kodyvideo 文件(片段、裁剪点、位置数据、背景音乐 + 音量)——作为安全网,也是在设备或浏览器源之间迁移项目(存储按源隔离)的方式;⋯ → 在某个位槽上保存备份,从关于页面或通过在应用内任意位置拖放 .kodyvideo 文件导入 - 发送到其他设备(Plus 功能):通过配对码 + 二维码连接两个浏览器;.kodyvideo 文件通过 WebRTC 数据通道传输(仅使用 STUN——通常限于同一 Wi-Fi)。片段不会上传到我们的服务器。接收功能在 /receive 免费提供。如果设备无法连接,保存备份仍然有效 - 可安装的 PWA(应用壳的 manifest + Workbox 服务工作者) - 无账户、无上传、无分析 大部分质量保证已实现自动化:npm run test:e2e 会运行 tests/e2e/ 目录下的 Playwright 测试套件(约 40 秒)。参见 manual-test-checklist.md 了解其覆盖范围和剩余需要真实设备检查的项目。 ## 架构 基于 Remix 3 (https://github.com/remix-run/remix) ([email protected],固定版本——v3 是候选发布版) 构建为纯客户端应用:remix/ui 组件使用 createRoot 渲染,无服务器端渲染。路由保持为一个微型应用内 history 路由器(见 router.tsx),而非 remix/spa,因为后者的框架导航在不支持 Navigation API 和 NavigateEvent.sourceElement 的浏览器(如 Firefox、旧版 iOS Safari)中会回退到完整的页面加载——对于相机应用,录制中发生重新加载是不可接受的。 src/ lib/storage.ts IndexedDB (idb) —— 项目、片段 blob + 缩略图、撤销 lib/project-actions.ts 页面的加载器/修改器辅助函数 lib/camera.ts 相机控制器(打开/翻转/变焦/镜头/麦克风生命周期) lib/recorder.ts 按住录制的 MediaRecorder 包装器(感知硬件编码器) lib/media.ts getUserMedia/权限/分享/下载辅助函数 lib/thumbs.ts 胶片条缩略图生成(按片段存储) lib/sync-*.ts Plus 的发送到设备功能(WebRTC + /api/sync 约会服务) lib/sheet-modal.ts 底部弹出式模态框(焦点陷阱、Esc、弹出栈) lib/export/ 导出引擎(见下文) components/record-screen 相机界面(捕捉、变焦、定时器、停靠) components/editor-screen 时间轴、裁剪、片段操作 pages/ 首页(项目位槽) + 项目(录制/编辑外壳) router.tsx 微型客户端路由器(路由模式匹配 + history) ### 章节与文件元数据 MP4 导出文件在每个片段边界处包含章节标记(Nero chpl 格式,由 lib/export/mp4-metadata.ts 在混流后注入),标题使用每个片段录制的时间(不含日历日期),此外还有 QuickTime 文本标签:项目标题 (©nam)、简短的创作说明 (©cmt / ©des —— 片段和照片数量、时长、音乐),以及编码器标识 (©too) 指向 kody.video (https://kody.video)。Kody Video Plus 用户可以在录制界面选择启用位置标记;之后片段会在 IndexedDB 中与片段数据一同存储设备坐标,且永远不会存入 MediaRecorder 的 blob 中。导出默认会省略这些坐标——以及拍摄日期——因此公开分享不会泄露拍摄地点或时间。另一个仅限 Plus 的导出选项会将日历日期和坐标添加到章节标题中,并在片段位置的多数集群中位数处(5 公里内)添加 ©xyz 地理标签,若无则退回到最后一个有位置信息的片段,并使用最后一个时间轴视频的录制时间戳 (©day 加上 mvhd/tkhd 的 creation_time)——这样相册应用就能将影片放置在正确的日期并添加地图标记。分享和保存操作也会使用相同的最后一个片段时间戳来设置 File.lastModified(Web Share 会将其复制到文件系统的创建/修改日期)。群晖 Photos 按这些文件日期排序,而非 MP4 内部时间戳。WebM 导出会跳过此注入(WebM 是 Matroska 的子集,不包含章节)。此功能之前录制的片段因缺少数据而优雅降级。 ### 导出管道 lib/export/ 使用两个引擎将片段拼接成一个文件: 1. Mediabunny + WebCodecs(首选,所有 Chromium 及最新 Firefox/Safari): 每个片段的原始样本由 Mediabunny (https://mediabunny.dev) 直接解复用并解码(无需播放节奏控制——帧供给以硬件速度运行,在后台标签页中也能工作,并遵循文件旋转元数据),在画布上与水印合成,然后由 Mediabunny 编码/混流,后者负责处理编解码器配置/包排序/容器细节。音频按片段解码并样本精确地追加,因此音频绝不会在片段间产生漂移;背压来自于等待编码器。容器/编解码器协商强烈偏好 MP4 (H.264/HEVC + AAC) ——这是在任何地方最易于分享的输出格式——仅在缺乏 MP4 编码器的非 iOS 平台上回退到 WebM (VP9/VP8 + Opus)。WebCodecs 无法解码的片段会采用实时元素泵回退方案。 2. 实时回退: 旧的 canvas.captureStream + MediaRecorder 拼接器,通过超时和处理异常片段进行了加固,用于不支持 WebCodecs 的浏览器。plan.ts 是一个经过单元测试的纯规划器,它提前限制裁剪点并丢弃无法播放的片段。分享流程会首先完成导出,然后在新的点击上执行分享/保存,以确保 Web Share API 始终获得所需的用户激活。 ### 录制质量 - 手机优先使用硬件 H.264(video/mp4/h264 MediaRecorder 类型),而非软件 VP9——软件编码是导致预览和片段在 Android 上掉帧的原因。 - 捕捉保持在 30fps(不采用丢帧捷径)。关于 -> 视频质量 可为新片段选择分辨率/比特率。无 Plus 时默认为标准(720p)。高清(1080p,约 10 Mbps)是 Plus 功能;省流模式是 720p 较低比特率。已保存的片段保持不变。比特率仍随实际轨道大小缩放。 - 录制界面上会预热一个实时 MediaRecorder,以便在用户按下录制键时,硬件编码器已经越过了约 170ms 的启动空档;录制会采用该会话并修剪掉预卷部分。 - 录制过程中,实时取景器保持在屏幕上;仅在松开录制时才附加额外的缩略图镜像 ``,因此按住录制时只有两个视频接收器(叠加层 + 编码器克隆),而非三个。录制克隆会设置 contentHint: motion,且编码器不会每 250ms 切割一次。 - 片段时长根据停止后的编码媒体测量(墙钟时间包含编码器启动延迟,会破坏裁剪/导出计算)。 - 已用时间计时器是一个叶子组件,直接通过一个 10Hz 的边界对齐定时器修改其文本节点(每帧的 rAF 循环会强制主线程 60fps),因此计时读数在捕捉期间绝不会触发页面重新渲染。 - 录制时会保持屏幕唤醒锁。 - 导出保持 1080p(长边 1920),在源文件间隙处保持最后一帧,使时间戳空洞表现为冻结而非卡顿,并且只丢弃距离小于 30fps 帧间时间一半的帧(保持抖动的 30fps;丢弃 60fps 的多余帧)。 ### Remix 数据流(显式更新,无钩子) - 组件是 Remix 3 的 setup + render 函数:状态存在于普通的 setup 作用域变量中,仅在显式调用 handle.update() 时发生重新渲染。 - 页面拥有其数据:每个页面在 setup 中加载 IndexedDB 状态并暴露 refresh() 方法;修改操作写入存储后调用 refresh()。 - 相机通过 ref() 混入连接(元素插入时启动,当元素的 abort 信号触发时停止)。 - Blob URL 在 ref() 混入中绑定/撤销(BlobVideo、BlobImage、TimelineThumbImage),当 blob 变化时从 render 重新同步。 - 弹出层使用 key={id} 重置;模态行为来自 lib/sheet-modal.ts。 - 定时器/提示使用从事件处理器启动的 requestAnimationFrame / setTimeout。 ### 存储(刷新安全 + 个人化) | 存储 | 内容 | |–––––|—————————————————––| | projects | JSON 元数据 + 有序的 clipIds | | clips | 片段元数据、Blob 媒体、胶片条缩略图 | | undo | 每个项目最后删除的片段(用于撤销) | | meta | 设置(maxProjects、最后打开的 id、引导流程) | | audio | 每个项目的背景音乐播放列表(blob、逐轨道裁剪/音量/淡入淡出) | 数据库名称:kody-video。Blob 永远不会离开设备,除非用户主动分享/下载。 ### 离线 / PWA vite-plugin-pwa 会生成一个服务工作者来预缓存应用壳(html/js/css/icons)。首次成功访问后: 1. 飞行模式仍可从缓存存储中加载 SPA。 2. 项目/片段数据继续来自 IndexedDB。 验证方法:npm run build && npm run preview,在线加载一次,然后 DevTools → Network → 离线(或操作系统飞行模式)并重新加载。 ## 浏览器限制 - iOS Safari: WebCodecs 音频支持不完整;实时回退引擎涵盖了它,但 Chromium(尤其是 Android)是主要目标平台。 - iOS 麦克风: 当麦克风和相机来自不同的 getUserMedia 调用时,WebKit 可能会传递静音音频轨道,因此在 iOS 上,麦克风会与相机一起获取并在预览打开期间保持(其他平台是每次录制时抓取麦克风)。在所有平台上,实时电平监视器会在静音录制时警告“麦克风未拾取声音”。 - iOS 外接麦克风(DJI 发射器、AirPods、有线耳机): iOS 默认将网页捕获固定到内置麦克风。相机打开后,应用会将 WebKit 的 navigator.audioSession 切换到 play-and-record——这是文档记载的用于将捕获路由到已连接外接麦克风的调整——并在相机关闭时恢复会话。尽力而为:路由仍由操作系统控制。 - 权限: 被拒绝的相机/麦克风权限必须在站点设置中重新启用;界面会提示此操作。 - 存储配额: 大型项目可能达到 IndexedDB 配额上限;软性 6 个项目上限有所帮助。 - 后台标签页: 录制应在前台进行;浏览器可能会限制捕获。 - 超广角 (0.5×): Android 通常将超广角/长焦镜头暴露为独立的后置相机,而不是 1× 以下的变焦——变焦芯片旁的镜头芯片用于切换它们。某些设备根本不向浏览器暴露额外的镜头;芯片在那里是隐藏的。将 Android 的逻辑多相机暴露给浏览器的手机(变焦范围低于 1×,三星常见)则通过变焦手势实现原生风格的无缝镜头切换——应用会在首次打开镜头时检测到这种镜头(循环切换芯片一次),并将其锁定用于所有后续的变焦操作。
相似文章
@kodykoala: Kody v2026.09.09 已发布。指南 → 文档位于 /docs。旧的扁平指南列表现已变为一个真正的文档站点,带有分组式固定侧边栏…
Kody v2026.09.09 版本发布,其新文档站点具备固定式分组侧边栏、分段式阅读顺序,并为AI智能体核心概念提供了专门的文档。
@kentcdodds: 此次发布的一部分使 Kody 更加稳定。我们离发布越来越近了!还有大量新的官方包…
Kody v2026.08.23 已发布,带来稳定性改进和首页上的新自动推进式代理对话功能,以及用于分叉的新官方包。
@kodykoala: Kody v2026.08.15 已发布。现在,打包应用、服务和订阅可以调用附加的远程连接。如果你已经连接了…
Kody v2026.08.15 已发布,使得在这个基于 Cloudflare Workers 构建的 AI 助手平台中,打包应用、服务和订阅能够调用附加的远程连接。
@kentcdodds:今日在@ProductHunt重新发布https://kody.video,并准备在本周晚些时候推出另一款Kody品牌产品…
Kent C. Dodds 在 Product Hunt 上重新发布 Kody Video,这是一款按住录制的视频分享工具。
@kodykoala: Kody v2026.08.06 已发布。套餐现为 Standard($5/月)和 Pro($20/月)。旧的 Pro 档现改为 Standard,价格不变…
Kody v2026.08.06 已发布,推出新的 Standard($5/月)和 Pro($20/月)定价档位,旧的 Pro 档现在变更为 Standard。Kody 是一个基于 MCP 的个人助理平台,构建在 Cloudflare Workers 上。