You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

117 lines
3.9 KiB

import 'package:eaimar/modules/translation/models/translation_export.dart';
import 'package:eaimar/modules/translation/models/translation_models.dart';
import 'package:flutter_test/flutter_test.dart';
TranslationItem _item(
DateTime at, {
String src = '你好',
String dst = 'Hello',
String srcLang = 'zh-CN',
String serviceId = '',
bool intermediate = false,
}) =>
TranslationItem(
sourceText: src,
translatedText: dst,
sourceLanguageCode: srcLang,
targetLanguageCode: srcLang == 'zh-CN' ? 'en-US' : 'zh-CN',
timestamp: at,
sessionId: 's',
serviceId: serviceId,
isIntermediate: intermediate,
);
void main() {
final t0 = DateTime(2026, 9, 18, 10, 0, 0);
test('只取录音开始之后的整句,时间是相对录音起点的毫秒', () {
final out = buildMeetingTranscript(
items: [
_item(t0.subtract(const Duration(seconds: 5)), src: '上一轮的'),
_item(t0.add(const Duration(seconds: 2))),
_item(t0.add(const Duration(seconds: 6)), src: '半句', intermediate: true),
_item(t0.add(const Duration(seconds: 9)), src: '第二句', dst: 'Second'),
],
recordingStartedAt: t0,
mode: 'simultaneous',
ownLanguageCode: 'zh-CN',
);
expect(out.length, 2);
expect(out[0]['starttime'], 2000);
expect(out[0]['endtime'], 9000); // 下一句开头
expect(out[0]['content'], '你好\nHello');
expect(out[0]['speaker'], ''); // 同传单向,不标说话人
expect(out[1]['starttime'], 9000);
expect(out[1]['endtime'], greaterThan(9000)); // 最后一句按字数估
});
test('通话翻译按 AST 的 serviceId 分说话人:A=0 本端 B=1 对端', () {
final out = buildMeetingTranscript(
items: [
_item(t0.add(const Duration(seconds: 1)), serviceId: 'A'),
_item(t0.add(const Duration(seconds: 3)),
src: 'Hi', dst: '嗨', srcLang: 'en-US', serviceId: 'B'),
],
recordingStartedAt: t0,
mode: 'call',
ownLanguageCode: 'zh-CN',
);
expect(out.map((e) => e['speaker']), ['Speaker_0', 'Speaker_1']);
});
test('面对面没有 serviceId,按这句话的语言分:说源语言的是本端', () {
final out = buildMeetingTranscript(
items: [
_item(t0.add(const Duration(seconds: 1))),
_item(t0.add(const Duration(seconds: 3)),
src: 'Hi', dst: '嗨', srcLang: 'en-US'),
],
recordingStartedAt: t0,
mode: 'faceToFace',
ownLanguageCode: 'zh-CN',
);
expect(out.map((e) => e['speaker']), ['Speaker_0', 'Speaker_1']);
});
test('暂停区间要从偏移里扣掉(面对面逐句松手即暂停)', () {
final out = buildMeetingTranscript(
items: [
_item(t0.add(const Duration(seconds: 2))),
// 3s~13s 暂停了 10 秒,这句在 15s 说的,音频里其实是第 5 秒
_item(t0.add(const Duration(seconds: 15)), src: '第二句', dst: ''),
],
recordingStartedAt: t0,
mode: 'faceToFace',
ownLanguageCode: 'zh-CN',
pauses: [
(t0.add(const Duration(seconds: 3)), t0.add(const Duration(seconds: 13)))
],
);
expect(out[0]['starttime'], 2000);
expect(out[0]['endtime'], 5000);
expect(out[1]['starttime'], 5000);
expect(out[1]['content'], '第二句'); // 没译文就只有原文一行
});
test('译文与原文相同时不重复', () {
final out = buildMeetingTranscript(
items: [_item(t0.add(const Duration(seconds: 1)), src: 'OK', dst: 'OK')],
recordingStartedAt: t0,
mode: 'simultaneous',
ownLanguageCode: 'zh-CN',
);
expect(out.single['content'], 'OK');
});
test('没有整句就返回空,调用方据此退回普通录音归档', () {
expect(
buildMeetingTranscript(
items: [_item(t0.add(const Duration(seconds: 1)), src: ' ')],
recordingStartedAt: t0,
mode: 'call',
ownLanguageCode: 'zh-CN',
),
isEmpty,
);
});
}