@aim-packages/subtitle 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -38,7 +38,10 @@ const optimizedSegments = tools.optimization.subtitleOptimization(segments, {
38
38
  const streamFilter = new filter.StreamFilter();
39
39
  streamFilter.add("敏感词", "***");
40
40
  const filteredText = streamFilter.feedAll("这是一个敏感词测试。");
41
- ```
41
+
42
+ // 字幕输出
43
+ const segments = [["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"]];
44
+ const srtContent = tools.output.outputSrt({ segments1: segments });
42
45
 
43
46
  ## 📚 API 文档
44
47
 
@@ -298,6 +301,71 @@ const merged = utils.consolidateSegments(segments, {
298
301
  2. 可选择性地为每个片段添加 `padding` 时间,扩展片段的开始和结束时间
299
302
  3. 如果添加了 `padding`,会自动处理重叠的片段,将它们合并
300
303
 
304
+ #### 颜色格式转换
305
+
306
+ ##### `convertHexColorToAssFormat(hexColor?: string): string`
307
+ 将十六进制颜色转换为 ASS 格式,用于字幕样式设置。
308
+
309
+ ```typescript
310
+ import { utils } from '@aim-packages/subtitle';
311
+
312
+ utils.convertHexColorToAssFormat("#FF0000"); // "&H0000FF00"
313
+ utils.convertHexColorToAssFormat("#00FF00"); // "&H0000FF00"
314
+ utils.convertHexColorToAssFormat("#0000FF"); // "&H00FF0000"
315
+ utils.convertHexColorToAssFormat("#FF0000FF"); // "&HFF00FF00"
316
+ utils.convertHexColorToAssFormat(); // ""
317
+ ```
318
+
319
+ **参数说明:**
320
+ - `hexColor?: string` - 十六进制颜色值,支持 7 位(#RRGGBB)和 9 位(#RRGGBBAA)格式
321
+
322
+ **作用:**
323
+ 1. 将十六进制颜色转换为 ASS 格式,用于字幕样式设置
324
+ 2. 支持 7 位和 9 位十六进制颜色格式
325
+ 3. 自动处理颜色通道的顺序转换(RGB 转 BGR)
326
+
327
+ ##### `convertHexColorToFFmpegFormat(hexColor: string): string`
328
+ 将十六进制颜色转换为 FFmpeg 格式,用于字幕样式设置。
329
+
330
+ ```typescript
331
+ import { utils } from '@aim-packages/subtitle';
332
+
333
+ utils.convertHexColorToFFmpegFormat("#FF0000"); // "&H0000FF00&"
334
+ utils.convertHexColorToFFmpegFormat("#00FF00"); // "&H0000FF00&"
335
+ utils.convertHexColorToFFmpegFormat("#0000FF"); // "&H00FF0000&"
336
+ utils.convertHexColorToFFmpegFormat("#FF0000FF"); // "&HFF00FF00&"
337
+ ```
338
+
339
+ **参数说明:**
340
+ - `hexColor: string` - 十六进制颜色值,支持 7 位(#RRGGBB)和 9 位(#RRGGBBAA)格式
341
+
342
+ **作用:**
343
+ 1. 将十六进制颜色转换为 FFmpeg 格式,用于字幕样式设置
344
+ 2. 支持 7 位和 9 位十六进制颜色格式
345
+ 3. 自动处理颜色通道的顺序转换(RGB 转 BGR)
346
+
347
+ #### 时间格式转换
348
+
349
+ ##### `convertTimeToAssFormat(str: string): string`
350
+ 将时间字符串转换为 ASS 字幕格式。
351
+
352
+ ```typescript
353
+ import { utils } from '@aim-packages/subtitle';
354
+
355
+ utils.convertTimeToAssFormat("01:30:45.123"); // "1:30:45.12"
356
+ utils.convertTimeToAssFormat("00:05:30.050"); // "0:05:30.05"
357
+ utils.convertTimeToAssFormat("00:00:00.999"); // "0:00:00.99"
358
+ ```
359
+
360
+ **参数说明:**
361
+ - `str: string` - 输入的时间字符串,格式为 HH:MM:SS.MMM
362
+
363
+ **作用:**
364
+ 1. 将标准时间格式字符串转换为 ASS 字幕文件所需的时间格式
365
+ 2. 支持 HH:MM:SS.MMM 格式的输入
366
+ 3. 确保时间轴的准确性和兼容性
367
+ 4. 自动处理毫秒的精度转换(3位转2位)
368
+
301
369
  ### Parser 字幕格式解析器
302
370
 
303
371
  Parser 模块提供了多种字幕格式的解析和转换功能,支持 SRT、VTT、ASS 等常见字幕格式,以及流式解析器用于实时处理。
@@ -908,6 +976,286 @@ repeatCheck.push({ st: "00:00:05", et: "00:00:07", text: "Hello" }); // 重复
908
976
  repeatCheck.end();
909
977
  ```
910
978
 
979
+ #### 字幕输出
980
+
981
+ 字幕输出模块提供了多种格式的字幕文件生成功能,支持SRT、VTT、LRC、ASS等主流字幕格式。
982
+
983
+ ##### `outputSrt(params: OutputTextParams): string`
984
+
985
+ 生成SRT格式的字幕文件。
986
+
987
+ **参数:**
988
+ - `params: OutputTextParams` - 输出参数配置
989
+
990
+ **返回值:**
991
+ - `string` - SRT格式的字幕内容
992
+
993
+ **示例:**
994
+ ```typescript
995
+ import { tools } from '@aim-packages/subtitle';
996
+
997
+ const segments1 = [
998
+ ["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"],
999
+ ["00:00:03,000", "00:00:05,000", "How are you?", "speaker2"]
1000
+ ];
1001
+
1002
+ const segments2 = [
1003
+ ["00:00:01,000", "00:00:03,000", "你好世界", "speaker1"],
1004
+ ["00:00:03,000", "00:00:05,000", "你好吗?", "speaker2"]
1005
+ ];
1006
+
1007
+ const speakerData = {
1008
+ settings: {
1009
+ speaker1: { spk: "speaker1", name: "张三", color: "#FF0000" },
1010
+ speaker2: { spk: "speaker2", name: "李四", color: "#00FF00" }
1011
+ },
1012
+ speakers: { speaker1: 1, speaker2: 1 },
1013
+ data: []
1014
+ };
1015
+
1016
+ const srtContent = tools.output.outputSrt({
1017
+ segments1,
1018
+ segments2,
1019
+ speakerData
1020
+ });
1021
+
1022
+ console.log(srtContent);
1023
+ // 输出:
1024
+ // 1
1025
+ // 00:00:01,000 --> 00:00:03,000
1026
+ // 张三: Hello world
1027
+ // 你好世界
1028
+ //
1029
+ // 2
1030
+ // 00:00:03,000 --> 00:00:05,000
1031
+ // 李四: How are you?
1032
+ // 你好吗?
1033
+ ```
1034
+
1035
+ ##### `outputVtt(params: OutputTextParams): string`
1036
+
1037
+ 生成VTT格式的字幕文件。
1038
+
1039
+ **参数:**
1040
+ - `params: OutputTextParams` - 输出参数配置
1041
+
1042
+ **返回值:**
1043
+ - `string` - VTT格式的字幕内容
1044
+
1045
+ **示例:**
1046
+ ```typescript
1047
+ import { tools } from '@aim-packages/subtitle';
1048
+
1049
+ const segments1 = [
1050
+ ["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"],
1051
+ ["00:00:03,000", "00:00:05,000", "How are you?", "speaker2"]
1052
+ ];
1053
+
1054
+ const vttContent = tools.output.outputVtt({
1055
+ segments1,
1056
+ speakerData
1057
+ });
1058
+
1059
+ console.log(vttContent);
1060
+ // 输出:
1061
+ // WEBVTT
1062
+ //
1063
+ // 00:00:01.000 --> 00:00:03.000
1064
+ // 张三: Hello world
1065
+ //
1066
+ // 00:00:03.000 --> 00:00:05.000
1067
+ // 李四: How are you?
1068
+ ```
1069
+
1070
+ ##### `outputLrc(params: OutputTextParams): string`
1071
+
1072
+ 生成LRC格式的字幕文件。
1073
+
1074
+ **参数:**
1075
+ - `params: OutputTextParams` - 输出参数配置
1076
+
1077
+ **返回值:**
1078
+ - `string` - LRC格式的字幕内容
1079
+
1080
+ **示例:**
1081
+ ```typescript
1082
+ import { tools } from '@aim-packages/subtitle';
1083
+
1084
+ const segments1 = [
1085
+ ["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"],
1086
+ ["00:00:03,000", "00:00:05,000", "How are you?", "speaker2"]
1087
+ ];
1088
+
1089
+ const lrcContent = tools.output.outputLrc({
1090
+ segments1,
1091
+ segments2,
1092
+ speakerData
1093
+ });
1094
+
1095
+ console.log(lrcContent);
1096
+ // 输出:
1097
+ // [01.000]张三: Hello world
1098
+ // [01.000]你好世界
1099
+ // [03.000]李四: How are you?
1100
+ // [03.000]你好吗?
1101
+ ```
1102
+
1103
+ ##### `outputAss(params: OutputTextParams): string`
1104
+
1105
+ 生成ASS格式的字幕文件,支持复杂的样式配置。
1106
+
1107
+ **参数:**
1108
+ - `params: OutputTextParams` - 输出参数配置
1109
+
1110
+ **返回值:**
1111
+ - `string` - ASS格式的字幕内容
1112
+
1113
+ **示例:**
1114
+ ```typescript
1115
+ import { tools } from '@aim-packages/subtitle';
1116
+
1117
+ const segments1 = [
1118
+ ["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"],
1119
+ ["00:00:03,000", "00:00:05,000", "How are you?", "speaker2"]
1120
+ ];
1121
+
1122
+ const segments2 = [
1123
+ ["00:00:01,000", "00:00:03,000", "你好世界", "speaker1"],
1124
+ ["00:00:03,000", "00:00:05,000", "你好吗?", "speaker2"]
1125
+ ];
1126
+
1127
+ const subtitleSettings = {
1128
+ disabled: false,
1129
+ stroke: true,
1130
+ shadow: true,
1131
+ background: true,
1132
+ backgroundColor: "#000000",
1133
+ main: {
1134
+ color: "#FFFFFF",
1135
+ borderColor: "#000000",
1136
+ size: 18,
1137
+ fontFamily: "Microsoft YaHei"
1138
+ },
1139
+ sub: {
1140
+ color: "#FFFF00",
1141
+ borderColor: "#000000",
1142
+ size: 14,
1143
+ fontFamily: "Microsoft YaHei"
1144
+ },
1145
+ position: {
1146
+ bottom: 20,
1147
+ left: 10
1148
+ },
1149
+ mode: "multiLang"
1150
+ };
1151
+
1152
+ const assContent = tools.output.outputAss({
1153
+ segments1,
1154
+ segments2,
1155
+ subtitleSettings,
1156
+ speakerData,
1157
+ isMac: false,
1158
+ reverse: false
1159
+ });
1160
+
1161
+ console.log(assContent);
1162
+ // 输出完整的ASS格式字幕文件,包含样式定义和字幕内容
1163
+ ```
1164
+
1165
+ ##### `outputTxt(params: OutputTextParams): string`
1166
+
1167
+ 生成TXT格式的纯文本文件,支持多种输出模式。
1168
+
1169
+ **参数:**
1170
+ - `params: OutputTextParams` - 输出参数配置
1171
+ - `useIndex?: boolean` - 是否显示索引编号
1172
+ - `useTimestamp?: boolean` - 是否显示时间戳
1173
+ - `useParagraph?: boolean` - 是否使用段落模式(按发言人分组或按chunkSize分组)
1174
+
1175
+ **返回值:**
1176
+ - `string` - TXT格式的文本内容
1177
+
1178
+ **功能特性:**
1179
+ - **段落模式**: 支持按说话人分组或按固定大小分块
1180
+ - **行模式**: 每个字幕片段单独一行
1181
+ - **多语言支持**: 自动检测中日韩语言,调整文本连接方式
1182
+ - **说话人支持**: 支持显示说话人名称和时间戳
1183
+
1184
+ **示例:**
1185
+ ```typescript
1186
+ import { tools } from '@aim-packages/subtitle';
1187
+
1188
+ const segments1 = [
1189
+ ["00:00:01,000", "00:00:03,000", "Hello world", "speaker1"],
1190
+ ["00:00:03,000", "00:00:05,000", "How are you?", "speaker1"],
1191
+ ["00:00:05,000", "00:00:07,000", "I'm fine, thank you.", "speaker2"]
1192
+ ];
1193
+
1194
+ const segments2 = [
1195
+ ["00:00:01,000", "00:00:03,000", "你好世界", "speaker1"],
1196
+ ["00:00:03,000", "00:00:05,000", "你好吗?", "speaker1"],
1197
+ ["00:00:05,000", "00:00:07,000", "我很好,谢谢。", "speaker2"]
1198
+ ];
1199
+
1200
+ const speakerData = {
1201
+ settings: {
1202
+ speaker1: { spk: "speaker1", name: "张三", color: "#FF0000" },
1203
+ speaker2: { spk: "speaker2", name: "李四", color: "#00FF00" }
1204
+ },
1205
+ speakers: { speaker1: 1, speaker2: 1 },
1206
+ data: []
1207
+ };
1208
+
1209
+ // 行模式 - 每个字幕片段单独一行
1210
+ const txtContent1 = tools.output.outputTxt({
1211
+ segments1,
1212
+ segments2,
1213
+ speakerData,
1214
+ useIndex: true,
1215
+ useTimestamp: true,
1216
+ useParagraph: false
1217
+ });
1218
+
1219
+ console.log(txtContent1);
1220
+ // 输出:
1221
+ // 0
1222
+ // 00:00:01,000 --> 00:00:03,000
1223
+ // 张三: Hello world
1224
+ // 你好世界
1225
+ //
1226
+ // 1
1227
+ // 00:00:03,000 --> 00:00:05,000
1228
+ // 张三: How are you?
1229
+ // 你好吗?
1230
+ //
1231
+ // 2
1232
+ // 00:00:05,000 --> 00:00:07,000
1233
+ // 李四: I'm fine, thank you.
1234
+ // 我很好,谢谢。
1235
+
1236
+ // 段落模式 - 按说话人分组
1237
+ const txtContent2 = tools.output.outputTxt({
1238
+ segments1,
1239
+ segments2,
1240
+ speakerData,
1241
+ useIndex: true,
1242
+ useTimestamp: true,
1243
+ useParagraph: true
1244
+ });
1245
+
1246
+ console.log(txtContent2);
1247
+ // 输出:
1248
+ // 1
1249
+ // 张三 - 00:00:01,000 --> 00:00:05,000
1250
+ // Hello world How are you?
1251
+ // 你好世界 你好吗?
1252
+ //
1253
+ // 2
1254
+ // 李四 - 00:00:05,000 --> 00:00:07,000
1255
+ // I'm fine, thank you.
1256
+ // 我很好,谢谢。
1257
+ ```
1258
+
911
1259
  #### 完整的字幕处理流程示例
912
1260
 
913
1261
  ```typescript
@@ -1011,6 +1359,92 @@ interface RepeatCheckOption {
1011
1359
  }
1012
1360
  ```
1013
1361
 
1362
+ ##### `OutputTextParams`
1363
+ ```typescript
1364
+ interface OutputTextParams {
1365
+ /** 主要字幕片段数组 */
1366
+ segments1: Array<ISegment>;
1367
+ /** 次要字幕片段数组(如翻译字幕) */
1368
+ segments2?: Array<ISegment>;
1369
+ /** 字幕样式设置 */
1370
+ subtitleSettings?: SubtitleSettings;
1371
+ /** 说话人数据 */
1372
+ speakerData?: SpeakerData | null;
1373
+ /** 本地化配置 */
1374
+ locale?: Record<string, any>;
1375
+
1376
+ // TXT格式相关
1377
+ /** 是否使用索引 */
1378
+ useIndex?: boolean;
1379
+ /** 是否使用时间戳 */
1380
+ useTimestamp?: boolean;
1381
+ /** 是否使用段落格式 */
1382
+ useParagraph?: boolean;
1383
+
1384
+ // Markdown格式相关
1385
+ /** 文档标题 */
1386
+ header?: string;
1387
+ /** 是否为Markdown格式 */
1388
+ isMd?: boolean;
1389
+ /** 分块大小 */
1390
+ chunkSize?: number;
1391
+
1392
+ // ASS格式相关
1393
+ /** 是否为Mac系统 */
1394
+ isMac?: boolean;
1395
+ /** 是否反转字幕顺序 */
1396
+ reverse?: boolean;
1397
+ }
1398
+ ```
1399
+
1400
+ ##### `ISegment`
1401
+ ```typescript
1402
+ type ISegment = [string, string, string, string | undefined]
1403
+ // [开始时间, 结束时间, 文本内容, 说话人标识]
1404
+ ```
1405
+
1406
+ ##### `SpeakerData`
1407
+ ```typescript
1408
+ interface SpeakerData {
1409
+ /** 说话人设置配置 */
1410
+ settings: Record<string, { spk: string; name?: string; color: string }>;
1411
+ /** 说话人统计 */
1412
+ speakers: Record<string, number>;
1413
+ /** 说话人时间数据 */
1414
+ data: { start: number; end: number; speaker: string }[];
1415
+ /** 其他选项 */
1416
+ options?: { speakerCount?: number; }
1417
+ }
1418
+ ```
1419
+
1420
+ ##### `SubtitleSettings`
1421
+ ```typescript
1422
+ interface SubtitleSettings {
1423
+ /** 是否禁用字幕 */
1424
+ disabled: boolean;
1425
+ /** 是否启用描边 */
1426
+ stroke: boolean;
1427
+ /** 是否启用阴影 */
1428
+ shadow: boolean;
1429
+ /** 是否启用背景 */
1430
+ background: boolean;
1431
+ /** 背景颜色 */
1432
+ backgroundColor: string;
1433
+ /** 主要字幕样式 */
1434
+ main: SubtitleTextStyle;
1435
+ /** 次要字幕样式 */
1436
+ sub: SubtitleTextStyle;
1437
+ /** 字幕位置 */
1438
+ position: SubtitlePosition;
1439
+ /** 字幕语言模式 */
1440
+ mode: SubtitleLanguage;
1441
+ /** 字幕顺序 */
1442
+ order?: number[];
1443
+ /** 水印样式 */
1444
+ watermark?: WatermarkStyle;
1445
+ }
1446
+ ```
1447
+
1014
1448
  ## 🏗️ 项目结构
1015
1449
 
1016
1450
  ```
@@ -1026,10 +1460,11 @@ src/
1026
1460
  ## 📋 模块功能概览
1027
1461
 
1028
1462
  ### Utils 模块
1029
- - **时间处理**: 时间格式化、秒数转换、数字补零等
1463
+ - **时间处理**: 时间格式化、秒数转换、数字补零、ASS 时间格式转换等
1030
1464
  - **语言处理**: 中日韩字符检测、语言代码转换等
1031
1465
  - **文本分块**: 按字符限制分块、字幕片段分块等
1032
1466
  - **字幕合并**: 合并相邻字幕片段、时间轴优化等
1467
+ - **颜色转换**: 十六进制颜色转 ASS 格式、FFmpeg 格式等
1033
1468
 
1034
1469
  ### Parser 模块
1035
1470
  - **格式转换**: SRT、VTT、ASS 格式之间的相互转换
@@ -1040,6 +1475,7 @@ src/
1040
1475
  - **语言检测**: 多语言文本的语言识别和概率分析
1041
1476
  - **文本分割**: 按句子、段落等规则分割文本
1042
1477
  - **字幕优化**: 重复检测、空白处理、质量优化等
1478
+ - **字幕输出**: 支持SRT、VTT、LRC、ASS等多种格式的字幕文件生成
1043
1479
 
1044
1480
  ### Filter 模块
1045
1481
  - **流式过滤**: 基于 DFA 算法的实时文本过滤