Skip to content

feat: 添加圆角背景的字幕支持,以及优化多项功能#954

Merged
WEIFENG2333 merged 13 commits intomasterfrom
fix-split
Jan 11, 2026
Merged

feat: 添加圆角背景的字幕支持,以及优化多项功能#954
WEIFENG2333 merged 13 commits intomasterfrom
fix-split

Conversation

@WEIFENG2333
Copy link
Copy Markdown
Owner

@WEIFENG2333 WEIFENG2333 commented Jan 11, 2026

Note

Adds a modern subtitle pipeline with selectable render modes and improves install/dev tooling.

  • New subtitle module: app/core/subtitle/ with rounded_renderer.py, ass_renderer.py, ass_utils.py, font_utils.py, text_utils.py, styles.py, __init__.py; font-aware wrapping, built‑in font loading, ASS↔PIL size ratio, preview APIs
  • Config/UI integration: new SubtitleRenderModeEnum; rounded‑bg style settings in cfg (font, colors, padding, spacing, etc.); style editor now supports ASS .txt and rounded‑bg .json, drag‑and‑drop preview background, and scaled previews
  • Video synthesis: SynthesisConfig extended (render_mode, subtitle_layout, ass_style, rounded_style); add_subtitles_with_style() routes to ASS or rounded‑bg; VideoSynthesisThread handles soft vs hard burn paths
  • ASS/ASR improvements: ASRData.to_ass() writes PlayResX/PlayResY, fixes dialogue order for SubtitleLayoutEnum, better translation detection; auto‑wrap uses real font metrics
  • Threads and utils: quieter logs, atexit pool cleanup, improved ModelScope download progress, path/save fixes, centralized get_subtitle_style()
  • Packaging/dev: add pyproject.toml (uv, ruff, pyright), new cross‑platform scripts/run.* and cleanup script; README updated with uv quick start; remove deprecated utils/configs (old ass wrapping, preview, pytest/pyright files)

Written by Cursor Bugbot for commit 42229c7. This will update automatically on new commits. Configure here.

liangweifeng and others added 13 commits December 2, 2025 22:34
- Increased `batch_size` and `thread_num` values in the configuration to improve performance.
- Reorganized import statements in the LLM module for clarity and consistency.
- Commented out the save operation in the subtitle thread to prevent unintended file writes.

These changes enhance the application's performance and maintainability.
… and commented-out code

- Removed the output name and split path variable definitions that were not in use.
- Commented out the save operation to prevent unintended file writes, enhancing code clarity and maintainability.
…nfiguration

- Moved the application startup logic into a dedicated `main()` function for better organization.
- Introduced a `pyproject.toml` file for project metadata and dependency management.
- Removed outdated configuration files (`pyrightconfig.json`, `pytest.ini`, `requirements.txt`, `run.bat`, `run.sh`) to streamline the project structure.
- Added new installation scripts for Windows and macOS/Linux to simplify the setup process.

These changes enhance code clarity, maintainability, and user experience during installation.
Add new app/core/subtitle module with ASS and rounded background rendering:
- ass_renderer.py: ASS style rendering with FFmpeg
- rounded_renderer.py: Pillow-based rounded background rendering
- font_utils.py: Font discovery and loading utilities
- ass_utils.py: ASS parsing and text wrapping utilities
- text_utils.py: Text measurement and wrapping helpers
- styles.py: RoundedBgStyle dataclass

Add SubtitleRenderModeEnum for switching between ASS and rounded modes.
Add rounded background style configuration options.
Remove deprecated utils: ass_auto_wrap.py, get_subtitle_style.py,
optimize_subtitles.py, subtitle_preview.py

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Major refactor of SubtitleStyleInterface to support both ASS style
and rounded background rendering modes:
- Add render mode switching with ComboBoxSettingCard
- Separate ASS style settings (primary/secondary fonts, colors, etc.)
- Add rounded background settings (font, colors, radius, padding, etc.)
- Add AssPreviewThread and RoundedBgPreviewThread for async preview
- Support drag-and-drop for background images
- Update preview text samples for better testing

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Update video synthesis pipeline to use new subtitle rendering system:
- VideoSynthesisThread: Support render_mode selection, generate temp SRT
  for soft subtitles, use add_subtitles_with_style for hard subtitles
- video_utils: Add add_subtitles_with_style() function to dispatch
  between ASS and rounded background rendering
- task_factory: Add get_rounded_style() method, update SynthesisConfig
  with render_mode, subtitle_layout, ass_style, and rounded_style

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Move runtime imports to module level for better code organization:
- translate/*: Move cache import to top
- split.py, main_window.py, log_window.py: Move atexit import
- platform_utils.py: Remove TYPE_CHECKING pattern
- setting_interface.py: Move TranscribeModelEnum import

Minor fixes:
- asr_data.py: Add video resolution params to to_ass(), improve
  translation detection logic
- MySettingCard.py: Add step parameter to SpinBoxSettingCard
- FasterWhisperSettingWidget.py: Move InfoBarPosition import
- transcript_thread.py: Fix save path string formatting

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add fonttools dependency for font metrics extraction
- Update pyright configuration:
  - Set pythonVersion to 3.12
  - Relax some type checking strictness
  - Add more excluded directories
  - Enable unused import/variable warnings

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Adjusted the order of subtitles in the ASS rendering logic to ensure that the translated text appears as "Default" and the original text as "Secondary" when translations are available.
- Added comments in Chinese to clarify the intended display order for both translation layouts.

These changes improve the clarity and correctness of subtitle rendering in the application.
…tting processes

- Removed unnecessary print statements in SubtitleOptimizer to enhance logging consistency.
- Updated error messages in split_by_llm.py to provide clearer guidance on model output errors and validation failures.
- Enhanced logging for folder and file opening failures in platform_utils.py to replace print statements with logger warnings.

These changes improve the overall robustness and clarity of error handling in the application.
- Removed the logic for calculating original image dimensions and scaling for preview rendering.
- Updated the preview thread initialization to rely on the rendering layer for automatic dimension retrieval, streamlining the code and improving performance.

These changes enhance the clarity and efficiency of the subtitle style interface.
- Introduced LXGW WenKai font for subtitle rendering.
- Added default subtitle style configuration in JSON format, including font size, text color, background color, and spacing settings.

These additions enhance the subtitle styling options available in the application.
Copilot AI review requested due to automatic review settings January 11, 2026 08:34
@WEIFENG2333 WEIFENG2333 merged commit 905a9cf into master Jan 11, 2026
3 of 4 checks passed
@claude
Copy link
Copy Markdown

claude bot commented Jan 11, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive support for rounded background subtitle rendering as an alternative to ASS-style subtitles and includes numerous optimizations across the codebase.

Changes:

  • Added new rounded background subtitle rendering mode with PIL-based image generation and FFmpeg overlay
  • Refactored subtitle rendering into a dedicated module with font utilities, text wrapping, and dual rendering modes (ASS/rounded)
  • Migrated from requirements.txt to pyproject.toml with uv package manager for improved dependency management
  • Improved installation scripts for macOS/Linux/Windows with automatic environment setup
  • Enhanced subtitle layout handling, improved error messages in LLM-based splitting, and optimized import organization

Reviewed changes

Copilot reviewed 52 out of 55 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
scripts/run.sh New installer script for macOS/Linux with uv integration
scripts/run.bat New installer script for Windows with uv integration
scripts/lint.sh Translated comments to English
run.sh, run.bat Removed old installation scripts
requirements.txt, pytest.ini, pyrightconfig.json Removed in favor of pyproject.toml
pyproject.toml New unified project configuration with dependencies and tool settings
main.py Wrapped application logic in main() function for script entry point
app/view/subtitle_style_interface.py Added rounded background style controls and preview, refactored to support dual render modes
app/view/video_synthesis_interface.py Updated info message for hard subtitle rendering
app/view/subtitle_interface.py Updated import paths for subtitle utilities
app/view/setting_interface.py Moved imports to top level
app/view/main_window.py Moved atexit import to top
app/view/log_window.py Moved platform/subprocess imports to top
app/thread/video_synthesis_thread.py Added style-based subtitle rendering with ASR data
app/thread/transcript_thread.py Simplified path construction
app/thread/subtitle_thread.py Removed unused split path generation
app/thread/modelscope_download_thread.py Refactored with progress callback class and output suppression
app/thread/batch_process_thread.py Removed inline functools import
app/core/utils/video_utils.py Added add_subtitles_with_style function for dual render mode support
app/core/utils/subtitle_preview.py, optimize_subtitles.py, get_subtitle_style.py, ass_auto_wrap.py Deleted, functionality moved to subtitle module
app/core/utils/platform_utils.py Removed TYPE_CHECKING, moved imports to top
app/core/translate/*.py Moved cache import to top level
app/core/task_factory.py Split style retrieval into ASS and rounded methods
app/core/subtitle/*.py New module with ASS/rounded renderers, font/text utilities
app/core/split/split_by_llm.py Improved error messages for validation failures
app/core/split/split.py Moved atexit import to top
app/core/optimize/optimize.py Removed debug print statement
app/core/llm/init.py Reordered imports alphabetically
app/core/entities.py Added SubtitleRenderModeEnum and updated SynthesisConfig
app/core/asr/asr_data.py Fixed ASS layout order, added video resolution parameters
app/config.py Added FONTS_PATH constant
app/components/MySettingCard.py Added configurable step parameter to SpinBoxSettingCard
app/components/FasterWhisperSettingWidget.py Moved imports to top
app/common/config.py Added rounded background style config, render mode selection, increased default batch/thread values
resource/subtitle_style/default.json New default rounded background style configuration
README.md Updated installation instructions for uv-based workflow

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

),
)

if match := re.search(r"Stream.*Video:.* (\d{2,5})x(\d{2,5})", result.stderr):
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The walrus operator usage here (:=) requires Python 3.8+. While pyproject.toml specifies requires-python = ">=3.10,<3.13", this is fine. However, this pattern could be clarified with a comment for maintainability.

Copilot uses AI. Check for mistakes.
# 添加反馈到对话
logger.warning(
f"断句验证失败,开始反馈循环 (第{step + 1}次尝试): {error_message}"
f"模型输出错误,断句验证失败,频繁出现建议更换更智能的模型。开始反馈循环 (第{step + 1}次尝试):\n {error_message}\n\n"
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message uses non-specific wording "模型输出错误,断句验证失败,频繁出现建议更换更智能的模型" (Model output error, sentence segmentation validation failed, if it occurs frequently suggest using a more intelligent model). This could be more specific about what went wrong and provide actionable guidance.

Suggested change
f"模型输出错误,断句验证失败,频繁出现建议更换更智能的模型。开始反馈循环 (第{step + 1}次尝试):\n {error_message}\n\n"
f"模型输出未通过断句验证,开始反馈循环 (第{step + 1}次尝试)"
f"\n验证失败原因:{error_message}"
"\n如多次失败,请检查输入文本是否过长或包含异常格式,并考虑调整模型或参数配置。\n"

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +27
# 颜色配置(支持 hex 格式,如 #RRGGBB 或 #RRGGBBAA)
bg_color: str = "#191919C8" # 背景颜色
text_color: str = "#FFFFFF" # 文字颜色

# 圆角和间距
corner_radius: int = 12 # 圆角半径
padding_h: int = 28 # 水平内边距
padding_v: int = 14 # 垂直内边距
margin_bottom: int = 60 # 底部外边距
line_spacing: int = 10 # 行间距
letter_spacing: int = 0 # 字符间距

# 字幕布局
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments within this file should be translated to English to match the English docstrings and improve international collaboration. For example, "# 颜色配置(支持 hex 格式,如 #RRGGBB 或 #RRGGBBAA)" should be in English.

Suggested change
# 颜色配置(支持 hex 格式,如 #RRGGBB #RRGGBBAA
bg_color: str = "#191919C8" # 背景颜色
text_color: str = "#FFFFFF" # 文字颜色
# 圆角和间距
corner_radius: int = 12 # 圆角半径
padding_h: int = 28 # 水平内边距
padding_v: int = 14 # 垂直内边距
margin_bottom: int = 60 # 底部外边距
line_spacing: int = 10 # 行间距
letter_spacing: int = 0 # 字符间距
# 字幕布局
# Color configuration (supports hex format, e.g. #RRGGBB or #RRGGBBAA)
bg_color: str = "#191919C8" # Background color
text_color: str = "#FFFFFF" # Text color
# Corner radius and spacing
corner_radius: int = 12 # Corner radius
padding_h: int = 28 # Horizontal padding
padding_v: int = 14 # Vertical padding
margin_bottom: int = 60 # Bottom margin
line_spacing: int = 10 # Line spacing
letter_spacing: int = 0 # Letter spacing
# Subtitle layout

Copilot uses AI. Check for mistakes.
subtitle_render_mode = OptionsConfigItem(
"SubtitleStyle",
"RenderMode",
SubtitleRenderModeEnum.ROUNDED_BG,
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default render mode is set to ROUNDED_BG, but the PR title says "添加圆角背景的字幕支持" (add rounded background subtitle support), suggesting this is a new feature. For backward compatibility and to avoid unexpected changes to existing users, the default should remain as ASS_STYLE, allowing users to opt-in to the new ROUNDED_BG mode.

Suggested change
SubtitleRenderModeEnum.ROUNDED_BG,
SubtitleRenderModeEnum.ASS_STYLE,

Copilot uses AI. Check for mistakes.
Comment on lines +141 to +142
batch_size = RangeConfigItem("Translate", "BatchSize", 10, RangeValidator(5, 50))
thread_num = RangeConfigItem("Translate", "ThreadNum", 10, RangeValidator(1, 100))
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default batch_size increased from 5 to 10, and thread_num from 8 to 10. These changes could increase memory consumption and API rate limit issues for users. Consider documenting why these defaults were increased or keeping the original conservative values.

Suggested change
batch_size = RangeConfigItem("Translate", "BatchSize", 10, RangeValidator(5, 50))
thread_num = RangeConfigItem("Translate", "ThreadNum", 10, RangeValidator(1, 100))
# Use conservative defaults to reduce memory usage and avoid hitting API rate limits.
batch_size = RangeConfigItem("Translate", "BatchSize", 5, RangeValidator(5, 50))
thread_num = RangeConfigItem("Translate", "ThreadNum", 8, RangeValidator(1, 100))

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +163
# 生成 ASS 内容
ass_content = ASS_TEMPLATE.format(
style_str=style_str,
dialogue=os.linesep.join(dialogue),
video_width=width,
video_height=height,
)

Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to 'ass_content' is unnecessary as it is redefined before this value is used.

Suggested change
# 生成 ASS 内容
ass_content = ASS_TEMPLATE.format(
style_str=style_str,
dialogue=os.linesep.join(dialogue),
video_width=width,
video_height=height,
)

Copilot uses AI. Check for mistakes.
),
)
styles[style.name] = style
except (ValueError, IndexError, KeyError):
Copy link

Copilot AI Jan 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

cfg.set(cfg.subtitle_style_name, style_name)
self._loading_style = False
self.updatePreview()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing flag cleanup on JSON parse failure

Medium Severity

In loadStyle, the _loading_style flag is set to True before calling _loadRoundedBgStyle, but if json.load() fails due to a corrupted or malformed JSON style file, an exception is raised and the flag is never reset to False. Since onRoundedBgSettingChanged and onAssSettingChanged both return early when _loading_style is True, all subsequent user changes to subtitle settings would be silently ignored until the application is restarted.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants