@rookiestar/eng-lang-tutor 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +1 -0
- package/backups/state_backup_20260227_063358.json +47 -0
- package/backups/state_backup_20260227_063405.json +47 -0
- package/backups/state_backup_20260227_064016.json +47 -0
- package/package.json +1 -1
- package/scripts/audio/composer.py +9 -4
- package/scripts/core/state_manager.py +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.2.4] - 2026-02-27
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **TTS voice selection**: Audio composer now automatically selects appropriate voices based on TTS provider
|
|
9
|
+
- Edge-TTS: `en-US-JennyNeural`, `en-US-EricNeural`
|
|
10
|
+
- XunFei: `catherine`, `henry`
|
|
11
|
+
- **CLI import paths**: Fixed broken imports in `state_manager.py` CLI module
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **npm package**: Removed automatic `pip install` from postinstall script
|
|
15
|
+
- Added `eng-lang-tutor-setup` CLI tool for manual dependency installation
|
|
16
|
+
- Supports `--venv`, `--user`, and `--check` options
|
|
17
|
+
- **Test coverage**: Added 38 new tests covering:
|
|
18
|
+
- `scripts/audio/utils.py` (6 tests)
|
|
19
|
+
- `scripts/audio/converter.py` (16 tests)
|
|
20
|
+
- `scripts/utils/helpers.py` (16 tests)
|
|
21
|
+
- **Test fixes**: Fixed pre-existing test failures in CLI and TTS modules
|
|
22
|
+
|
|
23
|
+
## [1.2.3] - 2026-02-27
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Version bump for npm publishing
|
|
27
|
+
|
|
28
|
+
## [1.2.0] - 2026-02-27
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- Initial npm package setup
|
|
32
|
+
|
|
33
|
+
## [1.0.1] - 2025-02-27
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **TTS voice selection**: Audio composer now automatically selects appropriate voices based on TTS provider
|
|
37
|
+
- Edge-TTS: `en-US-JennyNeural`, `en-US-EricNeural`
|
|
38
|
+
- XunFei: `catherine`, `henry`
|
|
39
|
+
- **CLI import paths**: Fixed broken imports in `state_manager.py` CLI module
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- **npm package**: Removed automatic `pip install` from postinstall script
|
|
43
|
+
- Added `eng-lang-tutor-setup` CLI tool for manual dependency installation
|
|
44
|
+
- Supports `--venv`, `--user`, and `--check` options
|
|
45
|
+
- **Test coverage**: Added 38 new tests covering:
|
|
46
|
+
- `scripts/audio/utils.py` (6 tests)
|
|
47
|
+
- `scripts/audio/converter.py` (16 tests)
|
|
48
|
+
- `scripts/utils/helpers.py` (16 tests)
|
|
49
|
+
- **Test fixes**: Fixed pre-existing test failures in CLI and TTS modules
|
|
50
|
+
|
|
5
51
|
## [1.0.1] - 2025-02-27
|
|
6
52
|
|
|
7
53
|
### Changed
|
package/README.md
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"initialized": false,
|
|
4
|
+
"onboarding_step": 0,
|
|
5
|
+
"completion_status": {
|
|
6
|
+
"quiz_completed_date": null,
|
|
7
|
+
"keypoint_view_history": []
|
|
8
|
+
},
|
|
9
|
+
"schedule": {
|
|
10
|
+
"keypoint_time": "06:45",
|
|
11
|
+
"quiz_time": "22:45",
|
|
12
|
+
"timezone": "Asia/Shanghai"
|
|
13
|
+
},
|
|
14
|
+
"user": {
|
|
15
|
+
"xp": 0,
|
|
16
|
+
"level": 1,
|
|
17
|
+
"streak": 0,
|
|
18
|
+
"streak_freeze": 0,
|
|
19
|
+
"gems": 0,
|
|
20
|
+
"badges": []
|
|
21
|
+
},
|
|
22
|
+
"preferences": {
|
|
23
|
+
"cefr_level": "B1",
|
|
24
|
+
"oral_written_ratio": 0.7,
|
|
25
|
+
"topics": {
|
|
26
|
+
"movies": 0.2,
|
|
27
|
+
"news": 0.15,
|
|
28
|
+
"gaming": 0.15,
|
|
29
|
+
"sports": 0.1,
|
|
30
|
+
"workplace": 0.2,
|
|
31
|
+
"social": 0.1,
|
|
32
|
+
"daily_life": 0.1
|
|
33
|
+
},
|
|
34
|
+
"tutor_style": "humorous",
|
|
35
|
+
"dedup_days": 14
|
|
36
|
+
},
|
|
37
|
+
"progress": {
|
|
38
|
+
"total_quizzes": 0,
|
|
39
|
+
"correct_rate": 0.0,
|
|
40
|
+
"last_study_date": null,
|
|
41
|
+
"perfect_quizzes": 0,
|
|
42
|
+
"expressions_learned": 0
|
|
43
|
+
},
|
|
44
|
+
"recent_topics": [],
|
|
45
|
+
"error_notebook": [],
|
|
46
|
+
"error_archive": []
|
|
47
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"initialized": false,
|
|
4
|
+
"onboarding_step": 0,
|
|
5
|
+
"completion_status": {
|
|
6
|
+
"quiz_completed_date": null,
|
|
7
|
+
"keypoint_view_history": []
|
|
8
|
+
},
|
|
9
|
+
"schedule": {
|
|
10
|
+
"keypoint_time": "06:45",
|
|
11
|
+
"quiz_time": "22:45",
|
|
12
|
+
"timezone": "Asia/Shanghai"
|
|
13
|
+
},
|
|
14
|
+
"user": {
|
|
15
|
+
"xp": 0,
|
|
16
|
+
"level": 1,
|
|
17
|
+
"streak": 0,
|
|
18
|
+
"streak_freeze": 0,
|
|
19
|
+
"gems": 0,
|
|
20
|
+
"badges": []
|
|
21
|
+
},
|
|
22
|
+
"preferences": {
|
|
23
|
+
"cefr_level": "B1",
|
|
24
|
+
"oral_written_ratio": 0.7,
|
|
25
|
+
"topics": {
|
|
26
|
+
"movies": 0.2,
|
|
27
|
+
"news": 0.15,
|
|
28
|
+
"gaming": 0.15,
|
|
29
|
+
"sports": 0.1,
|
|
30
|
+
"workplace": 0.2,
|
|
31
|
+
"social": 0.1,
|
|
32
|
+
"daily_life": 0.1
|
|
33
|
+
},
|
|
34
|
+
"tutor_style": "humorous",
|
|
35
|
+
"dedup_days": 14
|
|
36
|
+
},
|
|
37
|
+
"progress": {
|
|
38
|
+
"total_quizzes": 0,
|
|
39
|
+
"correct_rate": 0.0,
|
|
40
|
+
"last_study_date": null,
|
|
41
|
+
"perfect_quizzes": 0,
|
|
42
|
+
"expressions_learned": 0
|
|
43
|
+
},
|
|
44
|
+
"recent_topics": [],
|
|
45
|
+
"error_notebook": [],
|
|
46
|
+
"error_archive": []
|
|
47
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"initialized": false,
|
|
4
|
+
"onboarding_step": 0,
|
|
5
|
+
"completion_status": {
|
|
6
|
+
"quiz_completed_date": null,
|
|
7
|
+
"keypoint_view_history": []
|
|
8
|
+
},
|
|
9
|
+
"schedule": {
|
|
10
|
+
"keypoint_time": "06:45",
|
|
11
|
+
"quiz_time": "22:45",
|
|
12
|
+
"timezone": "Asia/Shanghai"
|
|
13
|
+
},
|
|
14
|
+
"user": {
|
|
15
|
+
"xp": 0,
|
|
16
|
+
"level": 1,
|
|
17
|
+
"streak": 0,
|
|
18
|
+
"streak_freeze": 0,
|
|
19
|
+
"gems": 0,
|
|
20
|
+
"badges": []
|
|
21
|
+
},
|
|
22
|
+
"preferences": {
|
|
23
|
+
"cefr_level": "B1",
|
|
24
|
+
"oral_written_ratio": 0.7,
|
|
25
|
+
"topics": {
|
|
26
|
+
"movies": 0.2,
|
|
27
|
+
"news": 0.15,
|
|
28
|
+
"gaming": 0.15,
|
|
29
|
+
"sports": 0.1,
|
|
30
|
+
"workplace": 0.2,
|
|
31
|
+
"social": 0.1,
|
|
32
|
+
"daily_life": 0.1
|
|
33
|
+
},
|
|
34
|
+
"tutor_style": "humorous",
|
|
35
|
+
"dedup_days": 14
|
|
36
|
+
},
|
|
37
|
+
"progress": {
|
|
38
|
+
"total_quizzes": 0,
|
|
39
|
+
"correct_rate": 0.0,
|
|
40
|
+
"last_study_date": null,
|
|
41
|
+
"perfect_quizzes": 0,
|
|
42
|
+
"expressions_learned": 0
|
|
43
|
+
},
|
|
44
|
+
"recent_topics": [],
|
|
45
|
+
"error_notebook": [],
|
|
46
|
+
"error_archive": []
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -87,9 +87,9 @@ class AudioComposer:
|
|
|
87
87
|
lead_in_silence: float = 1.0, # 引导语后留白
|
|
88
88
|
section_silence: float = 2.0, # 内容后留白(段落间隔)
|
|
89
89
|
dialogue_silence: float = 0.5, # 对话行之间留白
|
|
90
|
-
narrator_voice: str =
|
|
91
|
-
voice_a: str =
|
|
92
|
-
voice_b: str =
|
|
90
|
+
narrator_voice: str = None, # 旁白音色(None 时使用 TTS provider 默认值)
|
|
91
|
+
voice_a: str = None, # 对话 A 音色(None 时使用 TTS provider 默认值)
|
|
92
|
+
voice_b: str = None, # 对话 B 音色(None 时使用 TTS provider 默认值)
|
|
93
93
|
speed: float = 0.9 # 语速
|
|
94
94
|
) -> CompositionResult:
|
|
95
95
|
"""
|
|
@@ -110,6 +110,11 @@ class AudioComposer:
|
|
|
110
110
|
CompositionResult: 合成结果
|
|
111
111
|
"""
|
|
112
112
|
try:
|
|
113
|
+
# 使用 TTS provider 的默认音色(自动适配 Edge-TTS 或讯飞)
|
|
114
|
+
narrator_voice = narrator_voice or self.tts.get_voice_by_role("narrator")
|
|
115
|
+
voice_a = voice_a or self.tts.get_voice_by_role("dialogue_a")
|
|
116
|
+
voice_b = voice_b or self.tts.get_voice_by_role("dialogue_b")
|
|
117
|
+
|
|
113
118
|
output_path = Path(output_path)
|
|
114
119
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
115
120
|
|
|
@@ -213,7 +218,7 @@ class AudioComposer:
|
|
|
213
218
|
if not text:
|
|
214
219
|
continue
|
|
215
220
|
|
|
216
|
-
# A =
|
|
221
|
+
# A = EricNeural (男声), B = JennyNeural (女声)
|
|
217
222
|
voice = voice_a if speaker.upper() == "A" else voice_b
|
|
218
223
|
|
|
219
224
|
segment = self._synthesize_segment(
|
|
@@ -810,5 +810,8 @@ class StateManager:
|
|
|
810
810
|
|
|
811
811
|
# CLI interface - delegated to cli.py for better code organization
|
|
812
812
|
if __name__ == "__main__":
|
|
813
|
-
|
|
813
|
+
try:
|
|
814
|
+
from ..cli.cli import main
|
|
815
|
+
except ImportError:
|
|
816
|
+
from scripts.cli.cli import main
|
|
814
817
|
main()
|