자막 작업
This commit is contained in:
parent
5e5619e8d8
commit
f1d5c3ad50
11 changed files with 3182 additions and 238 deletions
100
bin/main.dart
100
bin/main.dart
|
|
@ -1,7 +1,8 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:dart_framework/log/log.dart';
|
||||
import 'package:dart_framework/subtitle/ParserSRT.dart';
|
||||
import 'package:dart_framework/subtitle/parser_smi.dart';
|
||||
import 'package:dart_framework/subtitle/parser_srt.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'package:dart_framework/core/application.dart';
|
||||
|
|
@ -10,88 +11,35 @@ import 'package:dart_framework/charset.dart';
|
|||
void main() async {
|
||||
Application(() async {
|
||||
var filePath = Platform.script.toFilePath(windows: true);
|
||||
var file = File('${path.dirname(path.dirname(filePath))}/test_euckr.smi');
|
||||
var file = File('${path.dirname(path.dirname(filePath))}/test_utf16le.smi');
|
||||
var bytes = file.readAsBytesSync();
|
||||
var encoding = Charset.detect(bytes, defaultEncoding: Utf8Codec());
|
||||
var encoding = Charset.detect(bytes);
|
||||
print(encoding);
|
||||
var result = eucKr.decode(bytes);
|
||||
// print(result);
|
||||
|
||||
//SRT
|
||||
// var parser = ParserSRT();
|
||||
// var subtitles = parser.getSubtitlesData(result!, SubtitleType.srt);
|
||||
// var index = 0;
|
||||
// for (var item in subtitles.subtitles) {
|
||||
// print('$index. ${item.text}');
|
||||
// index++;
|
||||
// }
|
||||
var result = encoding!.decode(bytes);
|
||||
|
||||
var ext = path.extension(file.path).toLowerCase();
|
||||
if (ext == '.smi') {
|
||||
//SMI
|
||||
var smi = ParserSMI();
|
||||
smi.getSubtitlesData(result!);
|
||||
|
||||
// var regExp = RegExp(
|
||||
// r'<SYNC Start=(\d+)><P Class=KRCC>',
|
||||
// caseSensitive: false,
|
||||
// multiLine: true,
|
||||
// );
|
||||
var parser = ParserSMI();
|
||||
var subtitles = parser.getSubtitlesData(result);
|
||||
var index = 0;
|
||||
for (var item in subtitles.subtitles) {
|
||||
print('$index. ${item.text}');
|
||||
index++;
|
||||
}
|
||||
} else if (ext == '.srt') {
|
||||
//SRT
|
||||
var parser = ParserSRT();
|
||||
var subtitles = parser.getSubtitlesData(result);
|
||||
var index = 0;
|
||||
for (var item in subtitles.subtitles) {
|
||||
print('$index. ${item.text}');
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}, (error, stack) {
|
||||
print(error);
|
||||
print(stack);
|
||||
exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
class ParserSMI {
|
||||
Subtitles getSubtitlesData(String subtitlesContent) {
|
||||
subtitlesContent = subtitlesContent.replaceAll(
|
||||
RegExp('<font (.*?=)(.*?>)|</font>|<b>|</b>| |<i>|</i>',
|
||||
caseSensitive: false, multiLine: false),
|
||||
'');
|
||||
|
||||
var regExp = RegExp(
|
||||
r'<SYNC Start=(\d+)><P Class=(.*?>)(\r|\n)*((((?!<SYNC|<\/BODY).*)(\r|\n))+)',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
final matches = regExp.allMatches(subtitlesContent).toList();
|
||||
final subtitleList = <Subtitle>[];
|
||||
Subtitle? lastItem;
|
||||
for (final regExpMatch in matches) {
|
||||
var startTime = Time(
|
||||
Duration(milliseconds: int.parse(regExpMatch.group(1).toString())));
|
||||
var content = regExpMatch.group(4)!;
|
||||
if (lastItem != null) {
|
||||
lastItem.endTime.duration = startTime.before;
|
||||
lastItem = null;
|
||||
}
|
||||
|
||||
if (!content.contains(' ')) {
|
||||
content = content
|
||||
.replaceAll(RegExp(r'(\r\n|\r|\n)', caseSensitive: false), '')
|
||||
.replaceAll(RegExp(r'(<br>|<\/br>)', caseSensitive: false), ' ')
|
||||
.trim();
|
||||
|
||||
if (content.isNotEmpty) {
|
||||
if (subtitleList.isNotEmpty &&
|
||||
content.contains(subtitleList.last.text)) {
|
||||
subtitleList.last.text = content;
|
||||
lastItem = subtitleList.last;
|
||||
} else {
|
||||
var endTime = Time(Duration());
|
||||
lastItem =
|
||||
Subtitle(startTime: startTime, endTime: endTime, text: content);
|
||||
subtitleList.add(lastItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var item in subtitleList) {
|
||||
print(
|
||||
'${item.startTime.toString()} --> ${item.endTime.toString()} >> ${item.text}');
|
||||
}
|
||||
|
||||
return Subtitles(subtitles: subtitleList);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -405,10 +405,11 @@ class Charset {
|
|||
|
||||
/// Default detect list
|
||||
static final defaultDetectOrder = <Encoding>[
|
||||
utf8,
|
||||
ascii,
|
||||
eucKr,
|
||||
eucJp,
|
||||
shiftJis,
|
||||
eucKr,
|
||||
gbk,
|
||||
windows874,
|
||||
latin1,
|
||||
|
|
|
|||
|
|
@ -11,32 +11,23 @@ class EucJPDecoder extends Converter<List<int>, String> {
|
|||
convert(input) {
|
||||
List<int> result = [];
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
final c1 = input[i];
|
||||
final List<int>? codes;
|
||||
var c1 = input[i];
|
||||
if (c1 <= 0x7E) {
|
||||
// ASCII Compatible
|
||||
codes = EUC_TABLE[c1];
|
||||
result.addAll(EUC_TABLE[c1] ?? []);
|
||||
} else if (c1 == 0x8e) {
|
||||
// Hiragana
|
||||
final c2 = input[++i];
|
||||
codes = EUC_TABLE[(c1 << 8) + c2];
|
||||
var c2 = input[++i];
|
||||
result.addAll(EUC_TABLE[(c1 << 8) + c2] ?? []);
|
||||
} else if (c1 == 0x8f) {
|
||||
// JIS X 0212
|
||||
final c2 = input[++i];
|
||||
final c3 = input[++i];
|
||||
codes = EUC_TABLE[(c1 << 16) + (c2 << 8) + c3];
|
||||
var c2 = input[++i];
|
||||
var c3 = input[++i];
|
||||
result.addAll(EUC_TABLE[(c1 << 16) + (c2 << 8) + c3] ?? []);
|
||||
} else {
|
||||
// JIS X 0208
|
||||
final c2 = input[++i];
|
||||
codes = EUC_TABLE[(c1 << 8) + c2];
|
||||
}
|
||||
if (codes == null) {
|
||||
if (_allowMalformed) {
|
||||
throw FormatException('Unfinished Euc-JP octet sequence', input, i);
|
||||
}
|
||||
result.add(unicodeReplacementCharacterRune);
|
||||
} else {
|
||||
result.addAll(codes);
|
||||
var c2 = input[++i];
|
||||
result.addAll(EUC_TABLE[(c1 << 8) + c2] ?? []);
|
||||
}
|
||||
}
|
||||
return utf8.decode(result);
|
||||
|
|
@ -46,10 +37,10 @@ class EucJPDecoder extends Converter<List<int>, String> {
|
|||
class EucJPEncoder extends Converter<String, List<int>> {
|
||||
const EucJPEncoder();
|
||||
@override
|
||||
List<int> convert(String input) {
|
||||
List<int> convert(String s) {
|
||||
List<int> result = [];
|
||||
for (int i = 0; i < input.length; i++) {
|
||||
var bytes = utf8.encode(input[i]);
|
||||
for (int i = 0; i < s.length; i++) {
|
||||
var bytes = utf8.encode(s[i]);
|
||||
var value = 0;
|
||||
|
||||
for (var i = 0, length = bytes.length; i < length; i++) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
const EUC_TABLE = {
|
||||
0x00: [0],
|
||||
0x01: [1],
|
||||
|
|
@ -715,6 +713,36 @@ const EUC_TABLE = {
|
|||
0xa8be: [226, 148, 165],
|
||||
0xa8bf: [226, 148, 184],
|
||||
0xa8c0: [226, 149, 130],
|
||||
0xada1: [226, 145, 160],
|
||||
0xada2: [226, 145, 161],
|
||||
0xada3: [226, 145, 162],
|
||||
0xada4: [226, 145, 163],
|
||||
0xada5: [226, 145, 164],
|
||||
0xada6: [226, 145, 165],
|
||||
0xada7: [226, 145, 166],
|
||||
0xada8: [226, 145, 167],
|
||||
0xada9: [226, 145, 168],
|
||||
0xadaa: [226, 145, 169],
|
||||
0xadab: [226, 145, 170],
|
||||
0xadac: [226, 145, 171],
|
||||
0xadad: [226, 145, 172],
|
||||
0xadae: [226, 145, 173],
|
||||
0xadaf: [226, 145, 174],
|
||||
0xadb0: [226, 145, 175],
|
||||
0xadb1: [226, 145, 176],
|
||||
0xadb2: [226, 145, 177],
|
||||
0xadb3: [226, 145, 178],
|
||||
0xadb4: [226, 145, 179],
|
||||
0xadb5: [226, 133, 160],
|
||||
0xadb6: [226, 133, 161],
|
||||
0xadb7: [226, 133, 162],
|
||||
0xadb8: [226, 133, 163],
|
||||
0xadb9: [226, 133, 164],
|
||||
0xadba: [226, 133, 165],
|
||||
0xadbb: [226, 133, 166],
|
||||
0xadbc: [226, 133, 167],
|
||||
0xadbd: [226, 133, 168],
|
||||
0xadbe: [226, 133, 169],
|
||||
0xb0a1: [228, 186, 156],
|
||||
0xb0a2: [229, 148, 150],
|
||||
0xb0a3: [229, 168, 131],
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
// ignore: file_names
|
||||
class ParserSRT {
|
||||
Subtitles getSubtitlesData(
|
||||
String subtitlesContent,
|
||||
SubtitleType subtitleType,
|
||||
) {
|
||||
RegExp regExp;
|
||||
if (subtitleType == SubtitleType.webvtt) {
|
||||
regExp = RegExp(
|
||||
r'((\d{2}):(\d{2}):(\d{2})\.(\d+)) +--> +((\d{2}):(\d{2}):(\d{2})\.(\d{3})).*[\r\n]+\s*((?:(?!\r?\n\r?).)*(\r\n|\r|\n)(?:.*))',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
} else if (subtitleType == SubtitleType.srt) {
|
||||
regExp = RegExp(
|
||||
r'((\d{2}):(\d{2}):(\d{2})\,(\d+)) +--> +((\d{2}):(\d{2}):(\d{2})\,(\d{3})).*[\r\n]+\s*((?:(?!\r?\n\r?).)*(\r\n|\r|\n)(?:.*))',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
} else {
|
||||
throw Exception('Incorrect subtitle type');
|
||||
}
|
||||
|
||||
final matches = regExp.allMatches(subtitlesContent).toList();
|
||||
final subtitleList = <Subtitle>[];
|
||||
|
||||
for (final regExpMatch in matches) {
|
||||
final startTimeHours = int.parse(regExpMatch.group(2)!);
|
||||
final startTimeMinutes = int.parse(regExpMatch.group(3)!);
|
||||
final startTimeSeconds = int.parse(regExpMatch.group(4)!);
|
||||
final startTimeMilliseconds = int.parse(regExpMatch.group(5)!);
|
||||
|
||||
final endTimeHours = int.parse(regExpMatch.group(7)!);
|
||||
final endTimeMinutes = int.parse(regExpMatch.group(8)!);
|
||||
final endTimeSeconds = int.parse(regExpMatch.group(9)!);
|
||||
final endTimeMilliseconds = int.parse(regExpMatch.group(10)!);
|
||||
final text = removeAllHtmlTags(regExpMatch.group(11)!);
|
||||
|
||||
final startTime = Time(Duration(
|
||||
hours: startTimeHours,
|
||||
minutes: startTimeMinutes,
|
||||
seconds: startTimeSeconds,
|
||||
milliseconds: startTimeMilliseconds,
|
||||
));
|
||||
final endTime = Time(Duration(
|
||||
hours: endTimeHours,
|
||||
minutes: endTimeMinutes,
|
||||
seconds: endTimeSeconds,
|
||||
milliseconds: endTimeMilliseconds,
|
||||
));
|
||||
|
||||
subtitleList.add(
|
||||
Subtitle(startTime: startTime, endTime: endTime, text: text.trim()),
|
||||
);
|
||||
}
|
||||
|
||||
return Subtitles(subtitles: subtitleList);
|
||||
}
|
||||
|
||||
String removeAllHtmlTags(String htmlText) {
|
||||
final exp = RegExp(
|
||||
'(<[^>]*>)',
|
||||
multiLine: true,
|
||||
);
|
||||
var newHtmlText = htmlText;
|
||||
exp.allMatches(htmlText).toList().forEach(
|
||||
(RegExpMatch regExpMatch) {
|
||||
newHtmlText = regExpMatch.group(0) == '<br>'
|
||||
? newHtmlText.replaceAll(regExpMatch.group(0)!, '\n')
|
||||
: newHtmlText.replaceAll(regExpMatch.group(0)!, '');
|
||||
},
|
||||
);
|
||||
|
||||
return newHtmlText;
|
||||
}
|
||||
}
|
||||
|
||||
class Subtitles {
|
||||
Subtitles({
|
||||
required this.subtitles,
|
||||
});
|
||||
final List<Subtitle> subtitles;
|
||||
}
|
||||
|
||||
class Subtitle {
|
||||
Subtitle({
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
required this.text,
|
||||
});
|
||||
Time startTime;
|
||||
Time endTime;
|
||||
String text;
|
||||
|
||||
List<Object?> get props => [startTime, endTime, text];
|
||||
}
|
||||
|
||||
enum SubtitleType {
|
||||
webvtt,
|
||||
srt,
|
||||
}
|
||||
|
||||
class Time {
|
||||
Time(Duration duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
late Duration _duration;
|
||||
Duration get duration => _duration;
|
||||
set duration(Duration value) {
|
||||
_duration = value;
|
||||
var timeStr = duration.toString();
|
||||
var timeArr = timeStr.substring(0, timeStr.lastIndexOf('.') + 4).split(':');
|
||||
hour = int.parse(timeArr[0]);
|
||||
minutes = int.parse(timeArr[1]);
|
||||
var secArr = timeArr[2].split('.');
|
||||
seconds = int.parse(secArr[0]);
|
||||
milliseconds = int.parse(secArr[1]);
|
||||
}
|
||||
|
||||
late int hour;
|
||||
late int minutes;
|
||||
late int seconds;
|
||||
late int milliseconds;
|
||||
|
||||
Duration get before {
|
||||
return Duration(milliseconds: duration.inMilliseconds - 1);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '${hour.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}.${milliseconds.toString().padLeft(3, '0')}';
|
||||
}
|
||||
}
|
||||
74
lib/subtitle/parser_base.dart
Normal file
74
lib/subtitle/parser_base.dart
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
abstract class ParserBase {
|
||||
static final RegExp _htmlRegExp = RegExp(
|
||||
'(<[^>]*>)',
|
||||
multiLine: true,
|
||||
);
|
||||
RegExp get regExp;
|
||||
Subtitles getSubtitlesData(String subtitlesContent);
|
||||
|
||||
String removeAllHtmlTags(String htmlText) {
|
||||
var newHtmlText = htmlText;
|
||||
_htmlRegExp.allMatches(htmlText).toList().forEach(
|
||||
(RegExpMatch regExpMatch) {
|
||||
newHtmlText = regExpMatch.group(0) == '<br>'
|
||||
? newHtmlText.replaceAll(regExpMatch.group(0)!, '\n')
|
||||
: newHtmlText.replaceAll(regExpMatch.group(0)!, '');
|
||||
},
|
||||
);
|
||||
|
||||
return newHtmlText;
|
||||
}
|
||||
}
|
||||
|
||||
class Subtitles {
|
||||
Subtitles({
|
||||
required this.subtitles,
|
||||
});
|
||||
final List<Subtitle> subtitles;
|
||||
}
|
||||
|
||||
class Subtitle {
|
||||
Subtitle({
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
required this.text,
|
||||
});
|
||||
Time startTime;
|
||||
Time endTime;
|
||||
String text;
|
||||
|
||||
List<Object?> get props => [startTime, endTime, text];
|
||||
}
|
||||
|
||||
class Time {
|
||||
Time(Duration duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
late Duration _duration;
|
||||
Duration get duration => _duration;
|
||||
set duration(Duration value) {
|
||||
_duration = value;
|
||||
var timeStr = duration.toString();
|
||||
var timeArr = timeStr.substring(0, timeStr.lastIndexOf('.') + 4).split(':');
|
||||
hour = int.parse(timeArr[0]);
|
||||
minutes = int.parse(timeArr[1]);
|
||||
var secArr = timeArr[2].split('.');
|
||||
seconds = int.parse(secArr[0]);
|
||||
milliseconds = int.parse(secArr[1]);
|
||||
}
|
||||
|
||||
late int hour;
|
||||
late int minutes;
|
||||
late int seconds;
|
||||
late int milliseconds;
|
||||
|
||||
Duration get before {
|
||||
return Duration(milliseconds: duration.inMilliseconds - 1);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '${hour.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}.${milliseconds.toString().padLeft(3, '0')}';
|
||||
}
|
||||
}
|
||||
57
lib/subtitle/parser_smi.dart
Normal file
57
lib/subtitle/parser_smi.dart
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import 'package:dart_framework/subtitle/parser_base.dart';
|
||||
|
||||
class ParserSMI extends ParserBase {
|
||||
@override
|
||||
RegExp get regExp => RegExp(
|
||||
r'<SYNC Start=(\d+)><P Class=(.*?>)(\r|\n)*((((?!<SYNC|<\/BODY).*)(\r|\n))+)',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
|
||||
@override
|
||||
Subtitles getSubtitlesData(String subtitlesContent) {
|
||||
subtitlesContent = subtitlesContent.replaceAll(
|
||||
RegExp('<font (.*?=)(.*?>)|</font>|<b>|</b>| |<i>|</i>',
|
||||
caseSensitive: false, multiLine: false),
|
||||
'');
|
||||
|
||||
final matches = regExp.allMatches(subtitlesContent).toList();
|
||||
final subtitleList = <Subtitle>[];
|
||||
Subtitle? lastItem;
|
||||
for (final regExpMatch in matches) {
|
||||
var startTime = Time(
|
||||
Duration(milliseconds: int.parse(regExpMatch.group(1).toString())));
|
||||
var content = regExpMatch.group(4)!;
|
||||
if (lastItem != null) {
|
||||
lastItem.endTime.duration = startTime.before;
|
||||
lastItem = null;
|
||||
}
|
||||
|
||||
if (!content.contains(' ')) {
|
||||
content = content
|
||||
.replaceAll(RegExp(r'(\r\n|\r|\n)', caseSensitive: false), '')
|
||||
.replaceAll(RegExp(r'(<br>|<\/br>)', caseSensitive: false), ' ')
|
||||
.trim();
|
||||
content = removeAllHtmlTags(content);
|
||||
|
||||
if (content.isNotEmpty) {
|
||||
if (subtitleList.isNotEmpty &&
|
||||
content.contains(subtitleList.last.text)) {
|
||||
subtitleList.last.text = content;
|
||||
lastItem = subtitleList.last;
|
||||
} else {
|
||||
var endTime = Time(Duration());
|
||||
lastItem =
|
||||
Subtitle(startTime: startTime, endTime: endTime, text: content);
|
||||
subtitleList.add(lastItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (var item in subtitleList) {
|
||||
// print(
|
||||
// '${item.startTime.toString()} --> ${item.endTime.toString()} >> ${item.text}');
|
||||
// }
|
||||
return Subtitles(subtitles: subtitleList);
|
||||
}
|
||||
}
|
||||
49
lib/subtitle/parser_srt.dart
Normal file
49
lib/subtitle/parser_srt.dart
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// ignore: file_names
|
||||
import 'package:dart_framework/subtitle/parser_base.dart';
|
||||
|
||||
class ParserSRT extends ParserBase {
|
||||
@override
|
||||
RegExp get regExp => RegExp(
|
||||
r'((\d{2}):(\d{2}):(\d{2})\,(\d+)) +--> +((\d{2}):(\d{2}):(\d{2})\,(\d{3})).*[\r\n]+\s*((?:(?!\r?\n\r?).)*(\r\n|\r|\n)(?:.*))',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
|
||||
@override
|
||||
Subtitles getSubtitlesData(String subtitlesContent) {
|
||||
final matches = regExp.allMatches(subtitlesContent).toList();
|
||||
final subtitleList = <Subtitle>[];
|
||||
|
||||
for (final regExpMatch in matches) {
|
||||
final startTimeHours = int.parse(regExpMatch.group(2)!);
|
||||
final startTimeMinutes = int.parse(regExpMatch.group(3)!);
|
||||
final startTimeSeconds = int.parse(regExpMatch.group(4)!);
|
||||
final startTimeMilliseconds = int.parse(regExpMatch.group(5)!);
|
||||
|
||||
final endTimeHours = int.parse(regExpMatch.group(7)!);
|
||||
final endTimeMinutes = int.parse(regExpMatch.group(8)!);
|
||||
final endTimeSeconds = int.parse(regExpMatch.group(9)!);
|
||||
final endTimeMilliseconds = int.parse(regExpMatch.group(10)!);
|
||||
final text = removeAllHtmlTags(regExpMatch.group(11)!);
|
||||
|
||||
final startTime = Time(Duration(
|
||||
hours: startTimeHours,
|
||||
minutes: startTimeMinutes,
|
||||
seconds: startTimeSeconds,
|
||||
milliseconds: startTimeMilliseconds,
|
||||
));
|
||||
final endTime = Time(Duration(
|
||||
hours: endTimeHours,
|
||||
minutes: endTimeMinutes,
|
||||
seconds: endTimeSeconds,
|
||||
milliseconds: endTimeMilliseconds,
|
||||
));
|
||||
|
||||
subtitleList.add(
|
||||
Subtitle(startTime: startTime, endTime: endTime, text: text.trim()),
|
||||
);
|
||||
}
|
||||
|
||||
return Subtitles(subtitles: subtitleList);
|
||||
}
|
||||
}
|
||||
10
lib/subtitle/parser_vtt.dart
Normal file
10
lib/subtitle/parser_vtt.dart
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import 'package:dart_framework/subtitle/parser_srt.dart';
|
||||
|
||||
class ParserVTT extends ParserSRT {
|
||||
@override
|
||||
RegExp get regExp => RegExp(
|
||||
r'((\d{2}):(\d{2}):(\d{2})\.(\d+)) +--> +((\d{2}):(\d{2}):(\d{2})\.(\d{3})).*[\r\n]+\s*((?:(?!\r?\n\r?).)*(\r\n|\r|\n)(?:.*))',
|
||||
caseSensitive: false,
|
||||
multiLine: true,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
OS だと iOS SDK, Android だと Java 組み込みの機能をそのまま使って変換しているので幅広い文字コードに対応しており、バグも恐らく少なくそれでいて高速であるため。
|
||||
逆に、これ以外のプラットフォームでは現状動作しない(macOS とか Windows)ので、現時点であまりいないとは思われますが、デスクトップアプリもサポートしたい場合には使えません。
|
||||
そういう人向けには、代わりに以下が使えます。
|
||||
2923
test_eucjp.srt
Normal file
2923
test_eucjp.srt
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue