感谢您对 FFmpeg GUI 项目的关注!我们欢迎所有形式的贡献。
为了营造开放和友好的环境,我们承诺:
- 使用友善和包容的语言
- 尊重不同的观点和经验
- 优雅地接受建设性批评
- 关注对社区最有利的事情
- 对其他社区成员表示同理心
- 使用性暗示的语言或图像
- 挑衅、侮辱或贬损性评论
- 公开或私下的骚扰
- 未经许可发布他人的私人信息
- 其他在专业环境中不适当的行为
贡献方式包括但不限于:
-
代码贡献
- 修复 Bug
- 添加新功能
- 性能优化
- 重构代码
-
文档贡献
- 改进文档
- 翻译文档
- 编写教程
-
测试贡献
- 编写单元测试
- 执行手动测试
- 报告 Bug
-
设计贡献
- UI/UX 改进
- 图标设计
- 界面优化
-
社区贡献
- 回答问题
- 参与讨论
- 推广项目
- Node.js >= 18.x LTS
- npm >= 8.x
- Git
- 代码编辑器(推荐 VSCode)
# Fork 仓库到您的账号
# 然后克隆您的 Fork
git clone https://github.com/YOUR_USERNAME/FFmpeg-GUI.git
cd FFmpeg-GUInpm installnpm run dev从 main 分支创建特性分支:
git checkout -b feature/your-feature-name
# 或
git checkout -b fix/issue-number-description分支命名规范:
feature/xxx- 新功能fix/xxx- Bug 修复docs/xxx- 文档更新refactor/xxx- 代码重构test/xxx- 测试相关chore/xxx- 构建/工具相关
src/
├── main/ # Electron 主进程
│ ├── ffmpeg/ # FFmpeg 核心功能
│ ├── ipc/ # IPC 处理器
│ ├── utils/ # 工具函数
│ └── index.ts # 主进程入口
├── renderer/ # React 渲染进程
│ └── src/
│ ├── components/ # React 组件
│ ├── pages/ # 页面组件
│ ├── router/ # 路由配置
│ ├── lib/ # 工具库
│ └── App.tsx # 应用入口
└── shared/ # 共享代码
├── constants.ts # 常量定义
├── types.ts # TypeScript 类型
└── format-presets.ts # 格式预设
| 文件/目录 | 用途 |
|---|---|
src/main/index.ts |
主进程入口,创建窗口 |
src/main/ipc/ |
IPC 通道处理器 |
src/main/ffmpeg/manager.ts |
FFmpeg 任务管理器 |
src/renderer/src/App.tsx |
渲染进程根组件 |
src/shared/types.ts |
全局类型定义 |
vite.config.ts |
Vite 配置 |
tsconfig.json |
TypeScript 配置 |
-
主进程功能(如新的 FFmpeg 操作)
// src/main/ffmpeg/your-feature.ts export class YourFeature { // 实现功能 } // src/main/ipc/yourHandlers.ts import { ipcMain } from 'electron'; import { IPC_CHANNELS } from '@shared/constants'; export function registerYourHandlers() { ipcMain.handle(IPC_CHANNELS.YOUR_CHANNEL, async () => { // 处理逻辑 }); }
-
渲染进程功能(如新的 UI 组件)
// src/renderer/src/components/YourComponent/YourComponent.tsx export function YourComponent() { // 组件实现 }
-
添加 IPC 通道
// src/shared/constants.ts export const IPC_CHANNELS = { // ... 现有通道 YOUR_CHANNEL: 'your:channel', };
# 运行所有测试
npm test
# 运行测试并查看覆盖率
npm run test:coverage
# 运行测试 UI
npm run test:ui// src/__tests__/your-feature.test.ts
import { describe, it, expect } from 'vitest';
import { yourFunction } from '../path/to/your-feature';
describe('YourFeature', () => {
it('should do something', () => {
const result = yourFunction();
expect(result).toBe(expected);
});
});# 类型检查
npm run type-check
# ESLint 检查
npm run lint
# 格式化代码
npm run format- 使用 TypeScript 严格模式
- 为所有公共 API 添加类型注解
- 避免使用
any,使用unknown代替 - 优先使用接口而非类型别名(公共 API)
示例:
// ✅ 好的
interface Task {
id: string;
status: TaskStatus;
progress: number;
}
function processTask(task: Task): void {
// ...
}
// ❌ 不好的
function processTask(task: any) {
// ...
}- 使用函数组件 + Hooks
- 组件名使用 PascalCase
- Props 接口命名为
ComponentNameProps - 使用
React.memo优化性能(需要时)
示例:
interface TaskCardProps {
task: Task;
onCancel: (taskId: string) => void;
}
export const TaskCard: React.FC<TaskCardProps> = ({ task, onCancel }) => {
// ...
};- 变量/函数: camelCase
- 类/接口/类型: PascalCase
- 常量: UPPER_SNAKE_CASE
- 私有成员: 前缀
_(可选)
// 变量和函数
const maxConcurrent = 2;
function handleTaskCancel() {}
// 类和接口
class FFmpegManager {}
interface TaskOptions {}
// 常量
const IPC_CHANNELS = {};
const MAX_RETRY_COUNT = 3;- 组件文件:PascalCase,如
TaskCard.tsx - 工具文件:camelCase,如
formatTime.ts - 测试文件:与源文件同名 +
.test,如TaskCard.test.tsx
- 为复杂逻辑添加注释
- 使用 JSDoc 注释公共 API
- 注释要简洁明了
/**
* 解析 FFmpeg 输出的时长信息
* @param output - FFmpeg 输出字符串
* @returns 时长(秒),解析失败返回 0
*/
export function parseDuration(output: string): number {
// 匹配格式:Duration: HH:MM:SS.ms
const match = output.match(/Duration: (\d{2}):(\d{2}):(\d{2}\.\d{2})/);
if (!match) return 0;
const [, hours, minutes, seconds] = match;
return Number(hours) * 3600 + Number(minutes) * 60 + Number(seconds);
}遵循 Conventional Commits 规范。
<type>(<scope>): <subject>
<body>
<footer>
feat: 新功能fix: Bug 修复docs: 文档更新style: 代码格式(不影响功能)refactor: 重构perf: 性能优化test: 测试相关chore: 构建/工具相关ci: CI 配置
main: 主进程renderer: 渲染进程ffmpeg: FFmpeg 相关ui: UI 组件build: 构建相关
# 新功能
git commit -m "feat(ffmpeg): add H.265 encoding support"
# Bug 修复
git commit -m "fix(ui): resolve progress bar display issue"
# 文档
git commit -m "docs: update installation guide"
# 重构
git commit -m "refactor(main): simplify task queue logic"feat(ffmpeg): add batch conversion support
- Add batch file upload functionality
- Implement parallel processing for multiple files
- Update UI to show batch progress
Closes #123
# 运行所有检查
npm run type-check
npm run lint
npm test- 更新 README.md(如果需要)
- 更新相关文档
- 添加 CHANGELOG 条目
- 推送分支到您的 Fork
git push origin feature/your-feature-name-
在 GitHub 上创建 Pull Request
-
填写 PR 模板
PR 标题应遵循提交规范:
feat: Add batch conversion support
fix: Resolve memory leak in task queue
docs: Update user guide for compression
## 变更类型
- [ ] Bug 修复
- [ ] 新功能
- [ ] 重构
- [ ] 文档更新
## 变更描述
简要描述此 PR 的变更内容
## 相关 Issue
Closes #issue_number
## 测试
- [ ] 添加了单元测试
- [ ] 所有测试通过
- [ ] 手动测试通过
## 检查清单
- [ ] 代码遵循项目规范
- [ ] 已运行 lint 和 type-check
- [ ] 更新了相关文档
- [ ] 添加了必要的注释- 积极响应 review 意见
- 及时修改代码
- 保持沟通
PR 通过 review 并且 CI 检查通过后,维护者会合并您的 PR。
- 搜索现有 Issues,避免重复
- 使用最新版本复现问题
- 收集必要信息
## Bug 描述
简要描述 bug
## 复现步骤
1. 打开应用
2. 点击「转换」
3. 选择文件
4. 观察到错误
## 预期行为
应该发生什么
## 实际行为
实际发生了什么
## 环境信息
- 操作系统:macOS 14.0
- 应用版本:0.1.0
- FFmpeg 版本:6.0
## 日志(如果有)
粘贴相关日志
## 截图(如果有)
添加截图欢迎提出新功能建议!
## 功能描述
清晰描述您想要的功能
## 使用场景
描述为什么需要这个功能
## 期望实现
描述您期望的实现方式
## 可选方案
是否有其他实现方式- 问题讨论: GitHub Discussions
- Bug 报告: GitHub Issues
- 邮件联系: dev@ffmpeg-gui.com
感谢所有贡献者的付出!您的贡献让这个项目变得更好。
查看所有贡献者:Contributors
再次感谢您的贡献!🎉