fixer_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. package sub_timeline_fixer
  2. import (
  3. "fmt"
  4. "github.com/allanpk716/ChineseSubFinder/internal/logic/sub_parser/ass"
  5. "github.com/allanpk716/ChineseSubFinder/internal/logic/sub_parser/srt"
  6. "github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
  7. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_helper"
  8. "github.com/allanpk716/ChineseSubFinder/internal/pkg/sub_parser_hub"
  9. "github.com/allanpk716/ChineseSubFinder/internal/pkg/vad"
  10. "github.com/allanpk716/ChineseSubFinder/internal/types/sub_timeline_fiexer"
  11. "github.com/james-bowman/nlp"
  12. "github.com/james-bowman/nlp/measures/pairwise"
  13. "gonum.org/v1/gonum/mat"
  14. "path/filepath"
  15. "strings"
  16. "testing"
  17. )
  18. func TestStopWordCounter(t *testing.T) {
  19. testDataPath := "../../../TestData/FixTimeline"
  20. testRootDir, err := my_util.CopyTestData(testDataPath)
  21. if err != nil {
  22. t.Fatal(err)
  23. }
  24. subParserHub := sub_parser_hub.NewSubParserHub(ass.NewParser(), srt.NewParser())
  25. bFind, info, err := subParserHub.DetermineFileTypeFromFile(filepath.Join(testRootDir, "R&M S05E10 - English.srt"))
  26. if err != nil {
  27. t.Fatal(err)
  28. }
  29. if bFind == false {
  30. t.Fatal("not match sub types")
  31. }
  32. allString := strings.Join(info.OtherLines, " ")
  33. s := SubTimelineFixer{}
  34. stopWords := s.StopWordCounter(strings.ToLower(allString), 5)
  35. print(len(stopWords))
  36. println(info.Name)
  37. }
  38. func TestTFIDF(t *testing.T) {
  39. testCorpus := []string{
  40. "The quick brown fox jumped over the lazy dog",
  41. "hey diddle diddle, the cat and the fiddle",
  42. "the cow jumped over the moon",
  43. "the little dog laughed to see such fun",
  44. "and the dish ran away with the spoon",
  45. }
  46. query := "the brown fox ran around the dog"
  47. vectoriser := nlp.NewCountVectoriser(StopWords...)
  48. transformer := nlp.NewTfidfTransformer()
  49. // set k (the number of dimensions following truncation) to 4
  50. reducer := nlp.NewTruncatedSVD(4)
  51. lsiPipeline := nlp.NewPipeline(vectoriser, transformer, reducer)
  52. // Transform the corpus into an LSI fitting the model to the documents in the process
  53. lsi, err := lsiPipeline.FitTransform(testCorpus...)
  54. if err != nil {
  55. fmt.Printf("Failed to process documents because %v", err)
  56. return
  57. }
  58. // run the query through the same pipeline that was fitted to the corpus and
  59. // to project it into the same dimensional space
  60. queryVector, err := lsiPipeline.Transform(query)
  61. if err != nil {
  62. fmt.Printf("Failed to process documents because %v", err)
  63. return
  64. }
  65. // iterate over document feature vectors (columns) in the LSI matrix and compare
  66. // with the query vector for similarity. Similarity is determined by the difference
  67. // between the angles of the vectors known as the cosine similarity
  68. highestSimilarity := -1.0
  69. var matched int
  70. _, docs := lsi.Dims()
  71. for i := 0; i < docs; i++ {
  72. similarity := pairwise.CosineSimilarity(queryVector.(mat.ColViewer).ColView(0), lsi.(mat.ColViewer).ColView(i))
  73. if similarity > highestSimilarity {
  74. matched = i
  75. highestSimilarity = similarity
  76. }
  77. }
  78. fmt.Printf("Matched '%s'", testCorpus[matched])
  79. // Output: Matched 'The quick brown fox jumped over the lazy dog'
  80. }
  81. func TestGetOffsetTimeV1(t *testing.T) {
  82. testDataPath := "../../../TestData/FixTimeline"
  83. testRootDir, err := my_util.CopyTestData(testDataPath)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. testRootDirYes := filepath.Join(testRootDir, "yes")
  88. testRootDirNo := filepath.Join(testRootDir, "no")
  89. subParserHub := sub_parser_hub.NewSubParserHub(ass.NewParser(), srt.NewParser())
  90. type args struct {
  91. enSubFile string
  92. ch_enSubFile string
  93. staticLineFileSavePath string
  94. }
  95. tests := []struct {
  96. name string
  97. args args
  98. want float64
  99. wantErr bool
  100. }{
  101. /*
  102. 这里有几个比较理想的字幕时间轴校正的示例
  103. */
  104. {name: "R&M S05E01", args: args{enSubFile: filepath.Join(testRootDirYes, "R&M S05E01 - English.srt"),
  105. ch_enSubFile: filepath.Join(testRootDirYes, "R&M S05E01 - 简英.srt"),
  106. staticLineFileSavePath: "bar.html"}, want: -6.42981818181818, wantErr: false},
  107. {name: "R&M S05E10", args: args{enSubFile: filepath.Join(testRootDirYes, "R&M S05E10 - English.ass"),
  108. ch_enSubFile: filepath.Join(testRootDirYes, "R&M S05E10 - 简英.ass"),
  109. staticLineFileSavePath: "bar.html"}, want: -6.335985401459854, wantErr: false},
  110. {name: "基地 S01E03", args: args{enSubFile: filepath.Join(testRootDirYes, "基地 S01E03 - English.ass"),
  111. ch_enSubFile: filepath.Join(testRootDirYes, "基地 S01E03 - 简英.ass"),
  112. staticLineFileSavePath: "bar.html"}, want: -32.09061538461539, wantErr: false},
  113. /*
  114. WTF,这部剧集
  115. Dan Brown'timelineFixer The Lost Symbol
  116. 内置的英文字幕时间轴是歪的,所以修正完了就错了
  117. */
  118. {name: "Dan Brown'timelineFixer The Lost Symbol - S01E01", args: args{
  119. enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E01.chinese(inside).ass"),
  120. ch_enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E01.chinese(简英,shooter).ass"),
  121. staticLineFileSavePath: "bar.html"},
  122. want: 1.3217821782178225, wantErr: false},
  123. {name: "Dan Brown'timelineFixer The Lost Symbol - S01E02", args: args{
  124. enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E02.chinese(inside).ass"),
  125. ch_enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E02.chinese(简英,subhd).ass"),
  126. staticLineFileSavePath: "bar.html"},
  127. want: -0.5253383458646617, wantErr: false},
  128. {name: "Dan Brown'timelineFixer The Lost Symbol - S01E03", args: args{
  129. enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E03.chinese(inside).ass"),
  130. ch_enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E03.chinese(繁英,xunlei).ass"),
  131. staticLineFileSavePath: "bar.html"},
  132. want: -0.505656, wantErr: false},
  133. {name: "Dan Brown'timelineFixer The Lost Symbol - S01E04", args: args{
  134. enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E04.chinese(inside).ass"),
  135. ch_enSubFile: filepath.Join(testRootDirNo, "Dan Brown'timelineFixer The Lost Symbol - S01E04.chinese(简英,zimuku).ass"),
  136. staticLineFileSavePath: "bar.html"},
  137. want: -0.633415, wantErr: false},
  138. /*
  139. 只有一个是字幕下载了一个错误的,其他的无需修正
  140. */
  141. {name: "Don't Breathe 2 (2021) - shooter-srt", args: args{
  142. enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(inside).srt"),
  143. ch_enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(简英,shooter).srt"),
  144. staticLineFileSavePath: "bar.html"},
  145. want: 0, wantErr: false},
  146. {name: "Don't Breathe 2 (2021) - subhd-srt error matched sub", args: args{
  147. enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(inside).srt"),
  148. ch_enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(简英,subhd).srt"),
  149. staticLineFileSavePath: "bar.html"},
  150. want: 0, wantErr: false},
  151. {name: "Don't Breathe 2 (2021) - xunlei-ass", args: args{
  152. enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(inside).ass"),
  153. ch_enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(简英,xunlei).ass"),
  154. staticLineFileSavePath: "bar.html"},
  155. want: 0, wantErr: false},
  156. {name: "Don't Breathe 2 (2021) - zimuku-ass", args: args{
  157. enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(inside).ass"),
  158. ch_enSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(简英,zimuku).ass"),
  159. staticLineFileSavePath: "bar.html"},
  160. want: 0, wantErr: false},
  161. /*
  162. 基地
  163. */
  164. {name: "Foundation (2021) - S01E01", args: args{
  165. enSubFile: filepath.Join(testRootDirNo, "Foundation (2021) - S01E01.chinese(inside).ass"),
  166. ch_enSubFile: filepath.Join(testRootDirNo, "Foundation (2021) - S01E01.chinese(简英,zimuku).ass"),
  167. staticLineFileSavePath: "bar.html"},
  168. want: 0, wantErr: false},
  169. {name: "Foundation (2021) - S01E02", args: args{
  170. enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E02.chinese(inside).ass"),
  171. ch_enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E02.chinese(简英,subhd).ass"),
  172. staticLineFileSavePath: "bar.html"},
  173. want: -30.624840, wantErr: false},
  174. {name: "Foundation (2021) - S01E03", args: args{
  175. enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E03.chinese(inside).ass"),
  176. ch_enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E03.chinese(简英,subhd).ass"),
  177. staticLineFileSavePath: "bar.html"},
  178. want: -32.085037037037054, wantErr: false},
  179. {name: "Foundation (2021) - S01E04", args: args{
  180. enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E04.chinese(inside).ass"),
  181. ch_enSubFile: filepath.Join(testRootDirYes, "Foundation (2021) - S01E04.chinese(简英,subhd).ass"),
  182. staticLineFileSavePath: "bar.html"},
  183. want: -36.885074, wantErr: false},
  184. {name: "Foundation (2021) - S01E04", args: args{
  185. enSubFile: filepath.Join(testRootDirNo, "Foundation (2021) - S01E04.chinese(inside).srt"),
  186. ch_enSubFile: filepath.Join(testRootDirNo, "Foundation (2021) - S01E04.chinese(繁英,shooter).srt"),
  187. staticLineFileSavePath: "bar.html"},
  188. want: 0, wantErr: false},
  189. /*
  190. The Card Counter
  191. */
  192. {name: "The Card Counter", args: args{
  193. enSubFile: filepath.Join(testRootDirNo, "The Card Counter (2021).chinese(inside).ass"),
  194. ch_enSubFile: filepath.Join(testRootDirNo, "The Card Counter (2021).chinese(简英,xunlei).ass"),
  195. staticLineFileSavePath: "bar.html"},
  196. want: 0, wantErr: false},
  197. {name: "The Card Counter", args: args{
  198. enSubFile: filepath.Join(testRootDirNo, "The Card Counter (2021).chinese(inside).ass"),
  199. ch_enSubFile: filepath.Join(testRootDirNo, "The Card Counter (2021).chinese(简英,shooter).ass"),
  200. staticLineFileSavePath: "bar.html"},
  201. want: 0.224844, wantErr: false},
  202. /*
  203. Kingdom Ashin of the North
  204. */
  205. {name: "Kingdom Ashin of the North - error matched sub", args: args{
  206. enSubFile: filepath.Join(testRootDirNo, "Kingdom Ashin of the North (2021).chinese(inside).ass"),
  207. ch_enSubFile: filepath.Join(testRootDirNo, "Kingdom Ashin of the North (2021).chinese(简英,subhd).ass"),
  208. staticLineFileSavePath: "bar.html"},
  209. want: 0, wantErr: false},
  210. /*
  211. Only Murders in the Building
  212. */
  213. {name: "Only Murders in the Building - S01E06", args: args{
  214. enSubFile: filepath.Join(testRootDirNo, "Only Murders in the Building - S01E06.chinese(inside).ass"),
  215. ch_enSubFile: filepath.Join(testRootDirNo, "Only Murders in the Building - S01E06.chinese(简英,subhd).ass"),
  216. staticLineFileSavePath: "bar.html"},
  217. want: 0, wantErr: false},
  218. {name: "Only Murders in the Building - S01E08", args: args{
  219. enSubFile: filepath.Join(testRootDirNo, "Only Murders in the Building - S01E08.chinese(inside).ass"),
  220. ch_enSubFile: filepath.Join(testRootDirNo, "Only Murders in the Building - S01E08.chinese(简英,subhd).ass"),
  221. staticLineFileSavePath: "bar.html"},
  222. want: 0, wantErr: false},
  223. /*
  224. Ted Lasso
  225. */
  226. {name: "Ted Lasso - S02E09", args: args{
  227. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E09.chinese(inside).ass"),
  228. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E09.chinese(简英,subhd).ass"),
  229. staticLineFileSavePath: "bar.html"},
  230. want: 0, wantErr: false},
  231. {name: "Ted Lasso - S02E09", args: args{
  232. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E09.chinese(inside).ass"),
  233. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E09.chinese(简英,zimuku).ass"),
  234. staticLineFileSavePath: "bar.html"},
  235. want: 0, wantErr: false},
  236. {name: "Ted Lasso - S02E10", args: args{
  237. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(inside).ass"),
  238. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(简英,subhd).ass"),
  239. staticLineFileSavePath: "bar.html"},
  240. want: 0, wantErr: false},
  241. {name: "Ted Lasso - S02E10", args: args{
  242. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(inside).ass"),
  243. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(简英,zimuku).ass"),
  244. staticLineFileSavePath: "bar.html"},
  245. want: 0, wantErr: false},
  246. {name: "Ted Lasso - S02E10", args: args{
  247. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(inside).ass"),
  248. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E10.chinese(简英,shooter).ass"),
  249. staticLineFileSavePath: "bar.html"},
  250. want: 0, wantErr: false},
  251. {name: "Ted Lasso - S02E11", args: args{
  252. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E11.chinese(inside).ass"),
  253. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E11.chinese(简英,subhd).ass"),
  254. staticLineFileSavePath: "bar.html"},
  255. want: 0, wantErr: false},
  256. {name: "Ted Lasso - S02E11", args: args{
  257. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E11.chinese(inside).ass"),
  258. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E11.chinese(简英,zimuku).ass"),
  259. staticLineFileSavePath: "bar.html"},
  260. want: 0, wantErr: false},
  261. {name: "Ted Lasso - S02E12", args: args{
  262. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E12.chinese(inside).ass"),
  263. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E12.chinese(简英,subhd).ass"),
  264. staticLineFileSavePath: "bar.html"},
  265. want: 0, wantErr: false},
  266. {name: "Ted Lasso - S02E12", args: args{
  267. enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E12.chinese(inside).ass"),
  268. ch_enSubFile: filepath.Join(testRootDirNo, "Ted Lasso - S02E12.chinese(简英,shooter).ass"),
  269. staticLineFileSavePath: "bar.html"},
  270. want: 0, wantErr: false},
  271. /*
  272. The Protégé
  273. */
  274. {name: "The Protégé", args: args{
  275. enSubFile: filepath.Join(testRootDirNo, "The Protégé (2021).chinese(inside).ass"),
  276. ch_enSubFile: filepath.Join(testRootDirNo, "The Protégé (2021).chinese(简英,zimuku).ass"),
  277. staticLineFileSavePath: "bar.html"},
  278. want: 0, wantErr: false},
  279. {name: "The Protégé", args: args{
  280. enSubFile: filepath.Join(testRootDirNo, "The Protégé (2021).chinese(inside).srt"),
  281. ch_enSubFile: filepath.Join(testRootDirNo, "The Protégé (2021).chinese(简英,shooter).srt"),
  282. staticLineFileSavePath: "bar.html"},
  283. want: 0, wantErr: false},
  284. /*
  285. The Witcher Nightmare of the Wolf
  286. */
  287. {name: "The Witcher Nightmare of the Wolf", args: args{
  288. enSubFile: filepath.Join(testRootDirNo, "The Witcher Nightmare of the Wolf.chinese(inside).ass"),
  289. ch_enSubFile: filepath.Join(testRootDirNo, "The Witcher Nightmare of the Wolf.chinese(简英,zimuku).ass"),
  290. staticLineFileSavePath: "bar.html"},
  291. want: 0, wantErr: false},
  292. /*
  293. What If…!
  294. */
  295. {name: "What If…! - S01E07", args: args{
  296. enSubFile: filepath.Join(testRootDirNo, "What If…! - S01E07.chinese(inside).ass"),
  297. ch_enSubFile: filepath.Join(testRootDirNo, "What If…! - S01E07.chinese(简英,subhd).ass"),
  298. staticLineFileSavePath: "bar.html"},
  299. want: 0, wantErr: false},
  300. {name: "What If…! - S01E09", args: args{
  301. enSubFile: filepath.Join(testRootDirNo, "What If…! - S01E09.chinese(inside).srt"),
  302. ch_enSubFile: filepath.Join(testRootDirNo, "What If…! - S01E09.chinese(简英,shooter).srt"),
  303. staticLineFileSavePath: "bar.html"},
  304. want: 0, wantErr: false},
  305. }
  306. timelineFixer := NewSubTimelineFixer(sub_timeline_fiexer.SubTimelineFixerConfig{
  307. MaxCompareDialogue: 3,
  308. MaxStartTimeDiffSD: 0.1,
  309. MinMatchedPercent: 0.1,
  310. MinOffset: 0.1,
  311. })
  312. for _, tt := range tests {
  313. t.Run(tt.name, func(t *testing.T) {
  314. bFind, infoBase, err := subParserHub.DetermineFileTypeFromFile(tt.args.enSubFile)
  315. if err != nil {
  316. t.Fatal(err)
  317. }
  318. if bFind == false {
  319. t.Fatal("sub not match")
  320. }
  321. /*
  322. 这里发现一个梗,内置的英文字幕导出的时候,有可能需要合并多个 Dialogue,见
  323. internal/pkg/sub_helper/sub_helper.go 中 MergeMultiDialogue4EngSubtitle 的实现
  324. */
  325. sub_helper.MergeMultiDialogue4EngSubtitle(infoBase)
  326. bFind, infoSrc, err := subParserHub.DetermineFileTypeFromFile(tt.args.ch_enSubFile)
  327. if err != nil {
  328. t.Fatal(err)
  329. }
  330. if bFind == false {
  331. t.Fatal("sub not match")
  332. }
  333. /*
  334. 这里发现一个梗,内置的英文字幕导出的时候,有可能需要合并多个 Dialogue,见
  335. internal/pkg/sub_helper/sub_helper.go 中 MergeMultiDialogue4EngSubtitle 的实现
  336. */
  337. sub_helper.MergeMultiDialogue4EngSubtitle(infoSrc)
  338. bok, got, sd, err := timelineFixer.GetOffsetTimeV1(infoBase, infoSrc, tt.args.ch_enSubFile+"-bar.html", tt.args.ch_enSubFile+".log")
  339. if (err != nil) != tt.wantErr {
  340. t.Errorf("GetOffsetTimeV1() error = %v, wantErr %v", err, tt.wantErr)
  341. return
  342. }
  343. // 在一个正负范围内都可以接受
  344. if got > tt.want-0.1 && got < tt.want+0.1 {
  345. } else {
  346. t.Errorf("GetOffsetTimeV1() got = %v, want %v", got, tt.want)
  347. }
  348. //if got != tt.want {
  349. // t.Errorf("GetOffsetTimeV1() got = %v, want %v", got, tt.want)
  350. //}
  351. if bok == true && got != 0 {
  352. _, err = timelineFixer.FixSubTimeline(infoSrc, got, tt.args.ch_enSubFile+FixMask+infoBase.Ext)
  353. if err != nil {
  354. t.Fatal(err)
  355. }
  356. }
  357. println(fmt.Sprintf("GetOffsetTimeV1: %fs SD:%f", got, sd))
  358. })
  359. }
  360. }
  361. func TestGetOffsetTimeV2(t *testing.T) {
  362. testDataPath := "../../../TestData/FixTimeline"
  363. testRootDir, err := my_util.CopyTestData(testDataPath)
  364. if err != nil {
  365. t.Fatal(err)
  366. }
  367. testRootDirYes := filepath.Join(testRootDir, "yes")
  368. testRootDirNo := filepath.Join(testRootDir, "no")
  369. subParserHub := sub_parser_hub.NewSubParserHub(ass.NewParser(), srt.NewParser())
  370. type args struct {
  371. baseSubFile string
  372. srcSubFile string
  373. staticLineFileSavePath string
  374. }
  375. tests := []struct {
  376. name string
  377. args args
  378. want float64
  379. wantErr bool
  380. }{
  381. /*
  382. 这里有几个比较理想的字幕时间轴校正的示例
  383. */
  384. {name: "R&M S05E01", args: args{baseSubFile: filepath.Join(testRootDirYes, "R&M S05E01 - English.srt"),
  385. srcSubFile: filepath.Join(testRootDirYes, "R&M S05E01 - 简英.srt"),
  386. staticLineFileSavePath: "bar.html"}, want: -6.42981818181818, wantErr: false},
  387. {name: "R&M S05E10", args: args{baseSubFile: filepath.Join(testRootDirYes, "R&M S05E10 - English.ass"),
  388. srcSubFile: filepath.Join(testRootDirYes, "R&M S05E10 - 简英.ass"),
  389. staticLineFileSavePath: "bar.html"}, want: -6.335985401459854, wantErr: false},
  390. {name: "基地 S01E03", args: args{baseSubFile: filepath.Join(testRootDirYes, "基地 S01E03 - English.ass"),
  391. srcSubFile: filepath.Join(testRootDirYes, "基地 S01E03 - 简英.ass"),
  392. staticLineFileSavePath: "bar.html"}, want: -32.09061538461539, wantErr: false},
  393. {name: "Don't Breathe 2 (2021) - shooter-srt", args: args{
  394. baseSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(inside).srt"),
  395. srcSubFile: filepath.Join(testRootDirNo, "Don't Breathe 2 (2021).chinese(简英,shooter).srt"),
  396. staticLineFileSavePath: "bar.html"},
  397. want: 0, wantErr: false},
  398. }
  399. timelineFixer := NewSubTimelineFixer(sub_timeline_fiexer.SubTimelineFixerConfig{
  400. MaxCompareDialogue: 3,
  401. MaxStartTimeDiffSD: 0.1,
  402. MinMatchedPercent: 0.1,
  403. MinOffset: 0.1,
  404. })
  405. for _, tt := range tests {
  406. t.Run(tt.name, func(t *testing.T) {
  407. bFind, infoBase, err := subParserHub.DetermineFileTypeFromFile(tt.args.baseSubFile)
  408. if err != nil {
  409. t.Fatal(err)
  410. }
  411. if bFind == false {
  412. t.Fatal("sub not match")
  413. }
  414. /*
  415. 这里发现一个梗,内置的英文字幕导出的时候,有可能需要合并多个 Dialogue,见
  416. internal/pkg/sub_helper/sub_helper.go 中 MergeMultiDialogue4EngSubtitle 的实现
  417. */
  418. //sub_helper.MergeMultiDialogue4EngSubtitle(infoBase)
  419. bFind, infoSrc, err := subParserHub.DetermineFileTypeFromFile(tt.args.srcSubFile)
  420. if err != nil {
  421. t.Fatal(err)
  422. }
  423. if bFind == false {
  424. t.Fatal("sub not match")
  425. }
  426. /*
  427. 这里发现一个梗,内置的英文字幕导出的时候,有可能需要合并多个 Dialogue,见
  428. internal/pkg/sub_helper/sub_helper.go 中 MergeMultiDialogue4EngSubtitle 的实现
  429. */
  430. //sub_helper.MergeMultiDialogue4EngSubtitle(infoSrc)
  431. bok, got, sd, err := timelineFixer.GetOffsetTimeV2(infoBase, infoSrc, tt.args.srcSubFile+"-bar.html", tt.args.srcSubFile+".log")
  432. if (err != nil) != tt.wantErr {
  433. t.Errorf("GetOffsetTimeV1() error = %v, wantErr %v", err, tt.wantErr)
  434. return
  435. }
  436. // 在一个正负范围内都可以接受
  437. if got > tt.want-0.1 && got < tt.want+0.1 {
  438. } else {
  439. t.Errorf("GetOffsetTimeV1() got = %v, want %v", got, tt.want)
  440. }
  441. //if got != tt.want {
  442. // t.Errorf("GetOffsetTimeV1() got = %v, want %v", got, tt.want)
  443. //}
  444. if bok == true && got != 0 {
  445. _, err = timelineFixer.FixSubTimeline(infoSrc, got, tt.args.srcSubFile+FixMask+infoBase.Ext)
  446. if err != nil {
  447. t.Fatal(err)
  448. }
  449. }
  450. println(fmt.Sprintf("GetOffsetTimeV1: %fs SD:%f", got, sd))
  451. })
  452. }
  453. }
  454. func TestSubTimelineFixer_GetOffsetTimeV3(t *testing.T) {
  455. subParserHub := sub_parser_hub.NewSubParserHub(ass.NewParser(), srt.NewParser())
  456. type fields struct {
  457. fixerConfig sub_timeline_fiexer.SubTimelineFixerConfig
  458. }
  459. type args struct {
  460. audioInfo vad.AudioInfo
  461. subFilePath string
  462. staticLineFileSavePath string
  463. debugInfoFileSavePath string
  464. }
  465. tests := []struct {
  466. name string
  467. fields fields
  468. args args
  469. want bool
  470. want1 float64
  471. want2 float64
  472. wantErr bool
  473. }{
  474. {name: "Rick and Morty - S05E10", args: args{audioInfo: vad.AudioInfo{FileFullPath: "C:\\Tmp\\Rick and Morty - S05E10\\英_1.pcm"}, subFilePath: "C:\\Tmp\\Rick and Morty - S05E10\\英_2.ass"}},
  475. }
  476. for _, tt := range tests {
  477. t.Run(tt.name, func(t *testing.T) {
  478. s := &SubTimelineFixer{
  479. fixerConfig: tt.fields.fixerConfig,
  480. }
  481. bok, fileInfo, err := subParserHub.DetermineFileTypeFromFile(tt.args.subFilePath)
  482. if err != nil {
  483. t.Fatal(err)
  484. }
  485. if bok == false {
  486. t.Fatal("DetermineFileTypeFromFile == false")
  487. }
  488. /*
  489. 这里发现一个梗,内置的英文字幕导出的时候,有可能需要合并多个 Dialogue,见
  490. internal/pkg/sub_helper/sub_helper.go 中 MergeMultiDialogue4EngSubtitle 的实现
  491. */
  492. //sub_helper.MergeMultiDialogue4EngSubtitle(fileInfo)
  493. got, got1, got2, err := s.GetOffsetTimeV3(tt.args.audioInfo, fileInfo, tt.args.staticLineFileSavePath, tt.args.debugInfoFileSavePath)
  494. if (err != nil) != tt.wantErr {
  495. t.Errorf("GetOffsetTimeV3() error = %v, wantErr %v", err, tt.wantErr)
  496. return
  497. }
  498. if got != tt.want {
  499. t.Errorf("GetOffsetTimeV3() got = %v, want %v", got, tt.want)
  500. }
  501. if got1 != tt.want1 {
  502. t.Errorf("GetOffsetTimeV3() got1 = %v, want %v", got1, tt.want1)
  503. }
  504. if got2 != tt.want2 {
  505. t.Errorf("GetOffsetTimeV3() got2 = %v, want %v", got2, tt.want2)
  506. }
  507. })
  508. }
  509. }