Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ on:
pull_request:
paths:
- '.github/workflows/python-test.yml'
- 'video_subtitle/**'
- 'cli/video_subtitle/**'
push:
branches:
- master
paths:
- '.github/workflows/python-test.yml'
- 'video_subtitle/**'
- 'cli/video_subtitle/**'

permissions:
contents: read
Expand All @@ -36,19 +36,19 @@ jobs:
shell: bash
run: |
set +e
python3 -m pip install -r video_subtitle/requirements.txt
python3 -m pip install -r cli/video_subtitle/requirements.txt
install_status="$?"
if [ "$install_status" -ne 0 ]; then
echo "failed=true" >> "$GITHUB_OUTPUT"
echo "::warning::python3 -m pip install -r video_subtitle/requirements.txt failed with exit code $install_status. Python tests were skipped. This workflow is advisory and does not block release packaging."
echo "::warning::python3 -m pip install -r cli/video_subtitle/requirements.txt failed with exit code $install_status. Python tests were skipped. This workflow is advisory and does not block release packaging."
exit 0
fi

python3 -m unittest video_subtitle/video_subtitle_test.py 2>&1 | tee python-test.log
python3 -m unittest cli/video_subtitle/video_subtitle_test.py 2>&1 | tee python-test.log
status="${PIPESTATUS[0]}"
if [ "$status" -ne 0 ]; then
echo "failed=true" >> "$GITHUB_OUTPUT"
echo "::warning::python3 -m unittest video_subtitle/video_subtitle_test.py failed with exit code $status. This workflow is advisory and does not block release packaging."
echo "::warning::python3 -m unittest cli/video_subtitle/video_subtitle_test.py failed with exit code $status. This workflow is advisory and does not block release packaging."
else
echo "failed=false" >> "$GITHUB_OUTPUT"
fi
Expand All @@ -59,4 +59,4 @@ jobs:
run: |
echo '## Python test reminder' >> "$GITHUB_STEP_SUMMARY"
echo '' >> "$GITHUB_STEP_SUMMARY"
echo '`python3 -m unittest video_subtitle/video_subtitle_test.py` failed. This workflow is advisory and does not block release packaging.' >> "$GITHUB_STEP_SUMMARY"
echo '`python3 -m unittest cli/video_subtitle/video_subtitle_test.py` failed. This workflow is advisory and does not block release packaging.' >> "$GITHUB_STEP_SUMMARY"
29 changes: 14 additions & 15 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:
- '.github/workflows/release.yml'
- '.github/workflows/go-test.yml'
- '.github/workflows/python-test.yml'
- 'docs/release.md'
- 'docs/**'
- 'README.MD'
- 'AGENTS.md'
- 'go.mod'
- 'go.sum'
- '**/*.go'
- 'video_subtitle/**'
- 'cli/video_subtitle/**'
- 'emby_plugins/video_subtitle/**'
- 'sample/life_tools/**'
push:
Expand Down Expand Up @@ -54,9 +54,9 @@ jobs:
- name: Compile video_subtitle Python files
run: |
python3 -m py_compile \
video_subtitle/video_subtitle.py \
video_subtitle/video_subtitle_test.py \
video_subtitle/lib/*.py
cli/video_subtitle/video_subtitle.py \
cli/video_subtitle/video_subtitle_test.py \
cli/video_subtitle/lib/*.py

- name: Run Emby plugin tests
run: dotnet test emby_plugins/video_subtitle/LifeTools.Emby.VideoSubtitle.sln --configuration Release
Expand Down Expand Up @@ -85,16 +85,15 @@ jobs:
out="$tmp/$pkg"
mkdir -p "$out/bin" "$out/sample/life_tools" "$out/docs"

GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/renameV1" ./renameV1/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/check_keywords" ./save_work/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/retry_exec" ./retry_exec/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/codex_hook_notify" ./codex_hook_notify/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/file_share" ./file_share/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/renameV1" ./cli/renameV1/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/check_keywords" ./cli/check_keywords/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/retry_exec" ./cli/retry_exec/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/codex_hook_notify" ./cli/codex_hook_notify/...
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags "-s -w" -o "$out/bin/file_share" ./cli/file_share/...

cp README.MD install.sh "$out/"
cp sample/life_tools/*.json "$out/sample/life_tools/"
cp docs/install.md docs/codex_hook_notify.md docs/file_share.md "$out/docs/"
cp docs/release.md "$out/docs/"
cp -R docs/. "$out/docs/"

(
cd "$tmp"
Expand All @@ -105,10 +104,10 @@ jobs:
video_pkg="life_tools_video_subtitle_source_${tag}"
video_out="$tmp/$video_pkg"
mkdir -p "$video_out/video_subtitle" "$video_out/sample/life_tools" "$video_out/docs"
cp -R video_subtitle/*.py video_subtitle/lib video_subtitle/prompts video_subtitle/requirements.txt "$video_out/video_subtitle/"
cp -R cli/video_subtitle/*.py cli/video_subtitle/lib cli/video_subtitle/prompts cli/video_subtitle/requirements.txt "$video_out/video_subtitle/"
cp sample/life_tools/video_subtitle.json "$video_out/sample/life_tools/"
cp README.MD install.sh "$video_out/"
cp docs/video_subtitle.md docs/release.md "$video_out/docs/"
cp -R docs/. "$video_out/docs/"
(
cd "$tmp"
zip -qr "$dist/$video_pkg.zip" "$video_pkg"
Expand All @@ -120,7 +119,7 @@ jobs:
mkdir -p "$plugin_out" "$plugin_out/docs" "$plugin_out/emby_plugins/video_subtitle"
cp emby_plugins/video_subtitle/src/LifeTools.Emby.VideoSubtitle.Emby/bin/Release/netstandard2.0/LifeTools.Emby.VideoSubtitle.Emby.dll "$plugin_out/"
cp emby_plugins/video_subtitle/install.sh emby_plugins/video_subtitle/build.sh "$plugin_out/emby_plugins/video_subtitle/"
cp docs/emby_video_subtitle_plugin.md docs/video_subtitle.md docs/release.md "$plugin_out/docs/"
cp -R docs/. "$plugin_out/docs/"
{
echo '# Life Tools Emby Video Subtitle Plugin'
echo
Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/swift-mac-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
pull_request:
paths:
- '.github/workflows/swift-mac-app.yml'
- 'mac_app/interview_timer/**'
- 'docs/interview_timer.md'
- 'gui/interview_timer/**'
- 'docs/gui/interview_timer.md'
- 'docs/release.md'
- 'README.MD'
- 'AGENTS.md'
Expand All @@ -16,8 +16,8 @@ on:
- 'v*'
paths:
- '.github/workflows/swift-mac-app.yml'
- 'mac_app/interview_timer/**'
- 'docs/interview_timer.md'
- 'gui/interview_timer/**'
- 'docs/gui/interview_timer.md'
- 'docs/release.md'
- 'README.MD'
- 'AGENTS.md'
Expand All @@ -39,23 +39,23 @@ jobs:
xcodebuild -version

- name: Run Swift tests
working-directory: mac_app/interview_timer
working-directory: gui/interview_timer
run: swift test

- name: Build executable
working-directory: mac_app/interview_timer
working-directory: gui/interview_timer
run: swift build --product InterviewTimerApp

- name: Build app bundle
working-directory: mac_app/interview_timer
working-directory: gui/interview_timer
run: ./scripts/build_app.sh

- name: Verify app bundle
run: |
set -euo pipefail
test -x mac_app/interview_timer/dist/InterviewTimer.app/Contents/MacOS/InterviewTimer
test -f mac_app/interview_timer/dist/InterviewTimer.app/Contents/Resources/AppIcon.icns
plutil -p mac_app/interview_timer/dist/InterviewTimer.app/Contents/Info.plist
test -x gui/interview_timer/dist/InterviewTimer.app/Contents/MacOS/InterviewTimer
test -f gui/interview_timer/dist/InterviewTimer.app/Contents/Resources/AppIcon.icns
plutil -p gui/interview_timer/dist/InterviewTimer.app/Contents/Info.plist

release:
name: Publish InterviewTimer release asset
Expand All @@ -69,7 +69,7 @@ jobs:
uses: actions/checkout@v4

- name: Build app bundle
working-directory: mac_app/interview_timer
working-directory: gui/interview_timer
run: ./scripts/build_app.sh

- name: Package unsigned app
Expand All @@ -83,7 +83,7 @@ jobs:
rm -rf "$dist_dir"
mkdir -p "$dist_dir"
ditto -c -k --keepParent \
mac_app/interview_timer/dist/InterviewTimer.app \
gui/interview_timer/dist/InterviewTimer.app \
"$dist_dir/${asset_name}.zip"

(
Expand Down
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ renameV1/tmp/
**/obj/

# SwiftPM and macOS app build artifacts
mac_app/**/.build/
mac_app/**/.swiftpm/
mac_app/**/dist/
mac_app/**/*.xcodeproj/
mac_app/**/*.xcworkspace/
gui/**/.build/
gui/**/.swiftpm/
gui/**/dist/
gui/**/*.xcodeproj/
gui/**/*.xcworkspace/
*.app
*.dSYM/
51 changes: 28 additions & 23 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@

## 仓库结构

- `renameV1/`:批量重命名命令行工具,入口是 `package main`。
- `save_work/`:敏感词检测工具,构建产物名是 `check_keywords`。
- `video_subtitle/`:单视频自动生成中文字幕工具,详细说明见 `docs/video_subtitle.md`。
- `emby_plugins/video_subtitle/`:Emby Server 插件,后端调用 `video_subtitle` 生成字幕,详细说明见 `docs/emby_video_subtitle_plugin.md`。
- `mac_app/`:macOS 图形应用集合;当前包含 `mac_app/interview_timer/`,说明见 `docs/interview_timer.md`。
- `docs/`:项目文档,`video_subtitle` 的使用和维护说明在 `docs/video_subtitle.md`。
- `cli/renameV1/`:批量重命名命令行工具,入口是 `package main`。
- `cli/check_keywords/`:敏感词检测工具,构建产物名是 `check_keywords`。
- `cli/retry_exec/`:命令失败重试和失败通知工具。
- `cli/codex_hook_notify/`:Codex lifecycle hook 飞书提醒工具。
- `cli/file_share/`:临时 HTTP 文件分享工具。
- `cli/video_subtitle/`:单视频自动生成中文字幕工具,详细说明见 `docs/cli/video_subtitle.md`。
- `emby_plugins/video_subtitle/`:Emby Server 插件,后端调用 `video_subtitle` 生成字幕,详细说明见 `docs/plugins/emby_video_subtitle.md`。
- `gui/interview_timer/`:macOS 面试悬浮计时 GUI 应用,说明见 `docs/gui/interview_timer.md`。
- `docs/cli/`:CLI 工具文档。
- `docs/plugins/`:插件程序文档。
- `docs/gui/`:GUI 程序文档。
- `sample/life_tools/`:示例配置文件。
- `renameV1/testData/`:`renameV1` 的测试数据,包含媒体文件、nfo、bif 等样例。
- `cli/renameV1/testData/`:`renameV1` 的测试数据,包含媒体文件、nfo、bif 等样例。
- `output/`:构建产物目录,不要把它当源码维护。

没有 `Makefile`、`justfile` 或 `Taskfile.yml`。优先遵循 README 和现有脚本。
Expand All @@ -34,11 +39,11 @@

该脚本会构建:

- `./output/renameV1` from `./renameV1/...`
- `./output/check_keywords` from `./save_work/...`
- `./output/retry_exec` from `./retry_exec/...`
- `./output/codex_hook_notify` from `./codex_hook_notify/...`
- `./output/file_share` from `./file_share/...`
- `./output/renameV1` from `./cli/renameV1/...`
- `./output/check_keywords` from `./cli/check_keywords/...`
- `./output/retry_exec` from `./cli/retry_exec/...`
- `./output/codex_hook_notify` from `./cli/codex_hook_notify/...`
- `./output/file_share` from `./cli/file_share/...`

测试优先使用:

Expand All @@ -49,13 +54,13 @@ go test ./...
也可以按包缩小范围:

```bash
go test ./renameV1
go test ./save_work
go test ./cli/renameV1
go test ./cli/check_keywords
```

涉及代码、配置、依赖或构建脚本的改动,交付前必须跑相应测试或构建。纯文档改动不需要假装跑 Go 测试,但要检查 diff。

macOS App 不走根目录 `build.sh`。修改 `mac_app/interview_timer` 时在该目录下验证:
macOS App 不走根目录 `build.sh`。修改 `gui/interview_timer` 时在该目录下验证:

```bash
swift test
Expand All @@ -79,35 +84,35 @@ swift build --product InterviewTimerApp

- `-rename` 会调用 `os.Rename` 执行真实重命名。
- 默认不要使用 `-skip_double_check`,除非测试环境可回滚。
- 修改重命名逻辑前,优先用 `renameV1/testData/` 或临时副本验证。
- 修改重命名逻辑前,优先用 `cli/renameV1/testData/` 或临时副本验证。
- 不要直接在真实 NAS、媒体库、下载目录上试新逻辑。
- 配置文件结构以 `ConfigRenameApp`、`ConfigRename`、`RenamePolicy` 为准。
- `fileNames` 里的 `skip` 是占位语义,用来跳过集数,不是普通文件名。
- 当前实现使用临时 UUID 文件名做两阶段重命名,避免目标名互相覆盖;改动时不能破坏这个保护。

## `check_keywords` 规则

`save_work` 目录构建出的命令叫 `check_keywords`。
`cli/check_keywords` 目录构建出的命令叫 `check_keywords`。

- 程序从 `stdin` 读取内容。
- `PrepareContents` 只保留以 `+` 开头的行,适配 `git diff` 新增内容检查。
- 默认配置路径是 `/etc/life_tools/check_keywords.json`。
- 示例配置在 `sample/life_tools/check_keywords.json`。
- git hook 示例在 `save_work/git-hooks/pre-commit`。
- git hook 示例在 `cli/check_keywords/git-hooks/pre-commit`。

不要把真实公司域名、内部仓库、密钥或敏感词写进仓库。示例只能保留假数据或公开无害字符串。

## `video_subtitle` 规则

`video_subtitle` 是 Python 工具,不走 Go 构建入口。完整使用方式、缓存结构和排障流程见 `docs/video_subtitle.md`。
`video_subtitle` 是 Python 工具,不走 Go 构建入口。完整使用方式、缓存结构和排障流程见 `docs/cli/video_subtitle.md`。

- 真实配置默认在 `/etc/life_tools/video_subtitle.json`,示例配置在 `sample/life_tools/video_subtitle.json`。
- 不要把 TOS、ASR、LLM、TMDB 的真实 key、token、预签名 URL 写入仓库或日志。
- 修改 ASR、split、translation、缓存、CLI 参数时,同步更新 `docs/video_subtitle.md` 和 README 中的简要入口。
- 修改 ASR、split、translation、缓存、CLI 参数时,同步更新 `docs/cli/video_subtitle.md` 和 README 中的简要入口。
- 涉及 LLM 输出结构时,必须保留本地 JSON 校验和失败响应落盘,不能只信 prompt。
- 修改 split 逻辑时,优先用已有 `utterances.json` 或离线 fake LLM 测试,不要直接从真实视频重新烧 ASR。
- 交付前至少运行:`PYTHONDONTWRITEBYTECODE=1 python3 -m unittest video_subtitle/video_subtitle_test.py`。
- 如果改了 Python 文件,还要运行 `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile video_subtitle/video_subtitle.py video_subtitle/video_subtitle_test.py video_subtitle/lib/*.py`。
- 交付前至少运行:`PYTHONDONTWRITEBYTECODE=1 python3 -m unittest cli/video_subtitle/video_subtitle_test.py`。
- 如果改了 Python 文件,还要运行 `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile cli/video_subtitle/video_subtitle.py cli/video_subtitle/video_subtitle_test.py cli/video_subtitle/lib/*.py`。


### `video_subtitle` 与 Emby 插件兼容性
Expand Down Expand Up @@ -153,7 +158,7 @@ emby_plugins/video_subtitle/install.sh --help
## Release Workflow 规则

`.github/workflows/release.yml` 负责 tag 发布,不是普通 CI。修改发布流程时要同时关注 Go、Python `video_subtitle` 和 Emby 插件三类产物。
`.github/workflows/swift-mac-app.yml` 负责 `mac_app/interview_timer` 的 Swift 单测、编译和未签名 `.app` 发布。
`.github/workflows/swift-mac-app.yml` 负责 `gui/interview_timer` 的 Swift 单测、编译和未签名 `.app` 发布。

- tag 触发规则保持 `v*`,避免普通分支 push 意外创建 Release;`pull_request` 只能做 dry-run,不能创建 Release。
- Go 测试放在 `.github/workflows/go-test.yml`,Python 单元测试放在 `.github/workflows/python-test.yml`,测试失败只能写 GitHub warning 和 summary,不能让 reminder workflow 或 release workflow 失败。
Expand Down
Loading
Loading