@hoanghong/speaking-core 0.4.2 → 0.5.0

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 CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.5.0
2
+
3
+ - Optional multi-criteria local pronunciation diagnostics with methods, limitations and unavailable scores.
4
+ - Compatible with older service responses.
5
+
6
+ ## 0.4.3
7
+
8
+ - Remove service addresses from public integration examples; no runtime changes.
9
+
1
10
  ## 0.4.2
2
11
 
3
12
  - Simplify public integration documentation; no runtime changes.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hoanghong/speaking-core
2
2
 
3
- SDK online cho người tự làm UI. Bản test 0.4.2 cài bằng `npm install ./vendor/hoanghong-speaking-core-0.4.2.tgz` từ bộ ZIP, chưa publish registry. Angular dùng @hoanghong/speaking-angular với component có sẵn; Flutter dùng fsel_speaking. MIT.
3
+ SDK online cho người tự làm UI. Bản test 0.5.0 cài bằng `npm install ./vendor/hoanghong-speaking-core-0.5.0.tgz` từ bộ ZIP, chưa publish registry. Angular dùng @hoanghong/speaking-angular với component có sẵn; Flutter dùng fsel_speaking. MIT.
4
4
 
5
5
  ## Đánh giá phát âm tiếng Anh Mỹ
6
6
 
@@ -78,15 +78,36 @@ createSpeakingGateway và các constructor cấu hình thủ công cũ vẫn đ
78
78
  Dùng `createSpeakingService({ appKey: "KEY_DUOC_FSEL_CAP" })` thay cho lời gọi không tham số. SDK gửi key khi cấp phiên; quota quản lý phía server, không có URL cần cấu hình. Key này là định danh ứng dụng có thể quan sát ở frontend, không có quyền quản trị. INVALID_APP_KEY/401 nghĩa là sai hoặc đã bị khóa; không tự fallback ẩn danh.
79
79
 
80
80
 
81
- ## Application key and service URL
81
+ ## Application key
82
82
 
83
- Pass the application key provided by FSEL as `appKey`. Quotas and key status are
84
- managed by the service. App keys identify an application and are visible in
85
- browser/mobile applications.
86
-
87
- The default service is https://ai-service.fsel.edu.vn/sdk. For a private deployment,
88
- set `baseUrl` to the absolute /sdk endpoint supplied by your service operator.
83
+ Pass the application key provided by FSEL as `appKey`. The SDK handles service
84
+ connections automatically. Quotas and key status are managed by the service.
85
+ App keys identify an application and are visible in browser/mobile applications.
89
86
 
90
87
  ```ts
91
- createSpeakingService({ appKey: 'YOUR_APP_KEY', baseUrl: 'https://your-service.example/sdk' });
88
+ createSpeakingService({ appKey: 'YOUR_APP_KEY' });
92
89
  ```
90
+
91
+
92
+ ## Multi-criteria pronunciation diagnostics (0.5.0)
93
+
94
+ Optional `breakdown` contains accuracy, completeness, fluency, prosody, pronunciation,
95
+ vocabulary, grammar and topic. Each has score (0–100 or null), status
96
+ (estimated/unavailable), method and reason. These are local diagnostics, not Azure
97
+ scores or calibrated grades. Older services may omit breakdown.
98
+
99
+ - Accuracy = 100 * matches / (matches + substitutions + insertions), at phoneme level.
100
+ - Completeness = 100 * (reference phonemes - omissions) / reference phonemes.
101
+ Substitutions count as covered; this is coverage, not correctness.
102
+ - Fluency is an energy continuity proxy = 100 * (1 - internal pause seconds / active span).
103
+ 20 ms RMS windows, threshold=max(0.005, 0.1*peak RMS), internal gaps >=250 ms.
104
+ Excludes leading/trailing silence; requires >=2 s audio and >=1 s active span.
105
+ Noise may inflate the value and intentional pauses may lower it; this is not VAD/native fluency.
106
+ - Prosody has no score. Pitch P90-P10 and standard deviation (semitones) are reported
107
+ with >=20 voiced frames and >=2 s audio. Variation does not imply correct intonation.
108
+ - Overall pronunciation and content scores remain null: no calibrated composite,
109
+ stress model, transcript/grammar evaluator or topic evaluator is configured.
110
+
111
+ errors counts phoneme matches/substitutions/omissions/insertions. signal.pauses are
112
+ acoustic intervals, not linguistic unexpected/missing breaks. Consult limitations
113
+ and version=local-diagnostics-v1 before interpreting estimates.
@@ -26,6 +26,47 @@ export interface PronunciationAcousticFrame {
26
26
  intensity_db: number | null;
27
27
  psd_power_per_hz: number[];
28
28
  }
29
+ /** Local estimates, not Azure-equivalent or calibrated educational scores. */
30
+ export interface PronunciationCriterion {
31
+ score: number | null;
32
+ status: 'estimated' | 'unavailable';
33
+ method: string;
34
+ reason: string | null;
35
+ }
36
+ export interface PronunciationBreakdown {
37
+ version: 'local-diagnostics-v1';
38
+ scope: 'scripted_phoneme_diagnostics';
39
+ calibrated: false;
40
+ accuracy: PronunciationCriterion;
41
+ completeness: PronunciationCriterion;
42
+ fluency: PronunciationCriterion;
43
+ prosody: PronunciationCriterion;
44
+ pronunciation: PronunciationCriterion;
45
+ vocabulary: PronunciationCriterion;
46
+ grammar: PronunciationCriterion;
47
+ topic: PronunciationCriterion;
48
+ errors: {
49
+ matches: number;
50
+ substitutions: number;
51
+ omissions: number;
52
+ insertions: number;
53
+ };
54
+ signal: {
55
+ speech_span_seconds: number;
56
+ internal_pause_seconds: number;
57
+ pause_ratio: number | null;
58
+ pauses: Array<{
59
+ start: number;
60
+ end: number;
61
+ duration: number;
62
+ }>;
63
+ energy_threshold: number;
64
+ pitch_range_semitones: number | null;
65
+ pitch_std_semitones: number | null;
66
+ voiced_frames: number;
67
+ };
68
+ limitations: string[];
69
+ }
29
70
  export interface PronunciationAssessment {
30
71
  reference_text: string;
31
72
  language: 'en-US';
@@ -41,6 +82,8 @@ export interface PronunciationAssessment {
41
82
  psd_frequencies_hz: number[];
42
83
  model: string;
43
84
  warnings: string[];
85
+ /** Optional for compatibility with older service versions. */
86
+ breakdown?: PronunciationBreakdown | null;
44
87
  }
45
88
  export interface AssessPronunciationOptions {
46
89
  referenceText: string;
@@ -42,6 +42,21 @@ export class PronunciationClient {
42
42
  typeof body.phoneme_similarity !== 'number' || !Array.isArray(body.comparisons)) {
43
43
  throw new SpeakingError('INVALID_RESPONSE', 'Invalid pronunciation assessment response');
44
44
  }
45
+ if (body.breakdown != null) {
46
+ const breakdown = body.breakdown;
47
+ const names = ['accuracy', 'completeness', 'fluency', 'prosody', 'pronunciation', 'vocabulary', 'grammar', 'topic'];
48
+ if (breakdown.version !== 'local-diagnostics-v1' || breakdown.calibrated !== false ||
49
+ breakdown.scope !== 'scripted_phoneme_diagnostics' || !breakdown.signal || !breakdown.errors ||
50
+ !Array.isArray(breakdown.limitations) || names.some(name => {
51
+ const criterion = breakdown[name];
52
+ return !criterion || typeof criterion.method !== 'string' ||
53
+ (criterion.status !== 'estimated' && criterion.status !== 'unavailable') ||
54
+ (criterion.status === 'unavailable' ? criterion.score !== null :
55
+ typeof criterion.score !== 'number' || !Number.isFinite(criterion.score) || criterion.score < 0 || criterion.score > 100);
56
+ })) {
57
+ throw new SpeakingError('INVALID_RESPONSE', 'Invalid pronunciation diagnostic breakdown');
58
+ }
59
+ }
45
60
  return body;
46
61
  }
47
62
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hoanghong/speaking-core",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Online speaking SDK: gateway configuration, realtime microphone and audio upload",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",