冒险解谜游戏中文网 ChinaAVG

标题: 【汉化工具系列 #2】指定wave格式转换为srt格式字幕(CPU版本) [打印本页]

作者: shane007    时间: 2023-9-4 11:03
标题: 【汉化工具系列 #2】指定wave格式转换为srt格式字幕(CPU版本)
本帖最后由 shane007 于 2023-9-4 12:57 编辑
2 m9 n5 s% B5 x
9 B. J# n% ?' h/ T% R6 z, r  B! M8 b 本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,8 P- B* Q& q7 T. ]3 p
使用时需要輸入语言,源文件路径和目标文件路径1 ^' A! G$ q: ], s+ ^4 [# p$ K, ?
最后是输出srt文件& v! I, ], K; c3 p+ |7 F7 d
1 s8 r: V2 T# i0 x' v/ Q; K
代码如下
. z: u9 y, G7 c% j以下这句用多线程可以增速,否则很慢
* i4 v: S0 Z7 S9 N) Y9 P- h以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。1 q" X! ?+ t$ c# V. |/ _
" t) f0 P5 ]) \8 E% |5 j4 f
& I& ^2 l3 P) r( r2 i) O
  1. var builder = factory.CreateBuilder()
    : v) R* c" T4 ]0 o
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码
% u, g' d& d7 ~  |; F
$ }$ d+ I& b+ N' M
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT0 ]6 M8 n  p' f' u, c' }

  2. 2 E- ~& U7 D( X1 T% d' j9 K0 x# E
  3. using System;
      ]7 h; m/ E4 b( D5 ~
  4. using System.Diagnostics;
    / ~9 O" i/ D- h  Y1 d
  5. using System.IO;, I# H; G+ ?! S0 t0 J$ N) f
  6. using System.Threading;8 q3 G& z' K/ D  ]7 u
  7. using System.Threading.Tasks;
    - ~1 }; J# ^; T  I& k+ F- B
  8. using CommandLine;
    ; w% n% U7 d8 ~# o( Y* e
  9. using Whisper.net;1 R* s/ L% |/ q, _8 O
  10. using Whisper.net.Ggml;0 x# Q& M2 |4 k3 }" o6 q
  11. using Whisper.net.Wave;
    9 p  l! \  ~. _
  12. 2 j, d2 E0 \9 ]. q8 ?6 G" m0 `$ a
  13. await Parser.Default.ParseArguments<Options>(args)
    5 P+ C# @9 ~* t- w' i
  14.     .WithParsedAsync(Demo);) G% K) u: \) X' ?0 {( O! M
  15. + z$ Q( s2 e0 Q$ O+ R
  16. async Task Demo(Options opt)
    0 K( B6 L; P4 l6 H; }

  17. , O6 f# o3 z9 T* Q
  18. {
    * F, g" J+ K% h3 G
  19.     if (!File.Exists(opt.ModelName))
      m* f+ a& K9 g2 L2 ^3 l# j1 i
  20.     {
    2 ~. ~" C" N1 V8 X
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");0 }9 f: n9 v1 j2 I: |( r8 L
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);
    ) Q$ s# z. I* x3 G) z, g
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);$ W, X+ S+ z/ a7 I4 h
  24.         await modelStream.CopyToAsync(fileWriter);) z3 o- k" |: Q% Q9 N2 h" l
  25.     }( G6 f9 d4 u' L$ [
  26. 1 m( y, z4 W4 p" r
  27.     switch (opt.Command)6 o' B4 ?. }0 D- b8 T) K7 n
  28.     {
    : {" ?9 m2 F$ [, K3 x# m( p
  29.         case "lang-detect":4 d7 O. U! \- Q1 \
  30.             LanguageIdentification(opt);$ N* w" c  {. h* |5 h; j
  31.             break;4 Y% F- m& N# u  Y- T
  32.         case "transcribe":
    - ^3 O4 T" Y- X* N& v( W- z, }1 n0 n
  33.         case "translate":! p" @& K9 L( s/ A
  34.             await FullDetection(opt);# [4 D, c) z* |1 S- {& _0 v
  35.             break;
    8 B" t2 l# X% h- A0 W0 V
  36.         default:5 O2 p/ u1 g2 l4 z: J. W; O9 X5 B
  37.             Console.WriteLine("Unknown command");
      W" T8 P7 A, y& k
  38.             break;
    9 p1 C( O7 H6 R6 v
  39.     }
    # r! x& `% D. [+ Z3 G3 ~; @4 _
  40. }
    2 T' F$ c% E, y, o0 R+ J

  41. 8 ~* v% x! r8 {" Q/ Z
  42. void LanguageIdentification(Options opt)9 P9 [5 L8 w. X: V' l) x
  43. {
    6 [6 n/ c" L2 s+ e& ]1 y# [
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);  J, P+ y3 `( S) P7 `( d
  45. ' ^+ w2 Q& R# e& ?5 n
  46.     // Same factory can be used by multiple task to create processors.
    + Q+ d, c6 w$ h" J
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);
    # [! W+ N5 f4 a. I

  48. 3 n: d5 q9 a" @4 z5 J" V
  49. /*    var builder = factory.CreateBuilder()8 m# X( m3 r5 G5 o/ t
  50.        .WithLanguage(opt.Language);*/
    , l$ m  |7 [* g
  51.     var builder = factory.CreateBuilder()% ~5 h' A/ X  B1 r0 [
  52.    .WithLanguage("english");
    3 |8 S1 c2 T  Y5 s, x1 h: e
  53.     using var processor = builder.Build();
    / q* a+ Q* t4 _' b7 I

  54. 3 E' k) |% a4 T7 n8 W- K- G
  55.     using var fileStream = File.OpenRead(opt.FileName);
    0 s$ J& N3 l; o/ N& C

  56.   X7 J& c6 y! ?) m) ^0 t
  57.     var wave = new WaveParser(fileStream);$ }/ W2 N5 I4 A! L! J8 S! S, ]

  58. # t, D% T& V/ S8 Y( _2 `
  59.     var samples = wave.GetAvgSamples();. I$ o2 z* o) E- b
  60. 6 L$ R/ n* Y6 Z' {
  61.     var language = processor.DetectLanguage(samples, speedUp: true);( W6 A5 m4 d: n5 Z, o3 e/ S
  62.     Console.WriteLine("Language is " + language);: M. y) J: r9 W7 T! e- M6 I% K" G* h
  63. }
    * |) M5 Z* o; i" ?

  64. ' t3 e0 N; h# l/ ?1 e
  65. async Task FullDetection(Options opt)
    : A: ?) \7 A4 G3 N6 R3 X  Q
  66. {; s/ u0 u/ l1 L9 Q" F, ~: v
  67.     // Same factory can be used by multiple task to create processors.
    0 w6 b$ Y5 j* w# n+ O
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);" E/ Z9 _6 q* w. A& \
  69. ; j0 x: j5 r5 P/ y* q# I. d9 p" Y
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);4 F# {4 R4 C8 o$ G
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");
    / y; u8 |: `1 Z/ }
  72.     string languageOption = Console.ReadLine();8 V5 k$ ^" A8 @/ c$ v/ `6 c
  73.     var builder = factory.CreateBuilder()
    ( I: P" n: p8 F& Y) ]6 T
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
    % Z: P4 G: w+ h/ H' s# I( `* X1 b

  75. / T8 B( u' Z6 c# B4 d6 k
  76.     if (opt.Command == "translate")
    , Z1 H: z5 B* r5 ^! h
  77.     {! P# l0 l5 ]- ]0 X! ^$ f
  78.         builder.WithTranslate();; j' X7 r; L4 x4 {8 W' ^
  79.     }
    " F. E& c  r' `' E1 |, ~
  80. ( ]& @( t1 I, q! v! T' @
  81.     WhisperProcessor processor = builder.Build();
    1 W$ v6 C# z! J& |  m6 b) e
  82.     7 b6 N8 _/ \8 h! G) ^
  83.     Console.WriteLine("请输入wave源文件目录:");3 e5 s' |5 h3 o0 q* V: V1 ?& Y" k/ m
  84.     string sourceDirectory = Console.ReadLine();
    " v5 [1 E8 N, Y* ?; b

  85. 0 [0 N$ l6 I% B# ^% N' H* `
  86.     Console.WriteLine("请输入目标文件目录:");& a8 e5 }- {( y2 x( U& P/ C( b+ q
  87.     string targetDirectory = Console.ReadLine();
    4 \# Z. i$ P+ H# K5 e
  88.   ^& W8 x$ g$ g
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    ) @& e8 g% m0 X( U9 L
  90.     {. Z# V1 U1 m- C  b" B
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    , U. K: _# Z6 d
  92.         return;
    4 g& q% W1 d+ z1 Y$ M( L0 p
  93.     }
    7 K4 {( m7 f8 q* T; r0 b( J- N) v
  94. - w6 A: n0 t; n; @* W! d1 p3 @
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);
    . u8 j0 d9 U( k; ~
  96. 1 R# L. d4 }+ H4 e0 t& V$ x
  97.     Console.WriteLine("处理完成!");
    / b  P7 p$ d' N6 j' M+ T' ^% j
  98. ; l" T% i5 ^7 e
  99. }
    4 o9 V  n: i+ o/ e* }2 g* U
  100. static async Task ProcessFilesAsync(WhisperProcessor processor,
    9 [' r3 c6 ?# P2 I! k) }
  101.     string sourceDirectory, string targetDirectory)1 N8 F/ A1 M4 L1 P$ j
  102. {9 P5 N& b& i) @# ]- I: s7 ~
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);
    + m0 |3 p3 U5 s2 `# X, l( @
  104. 8 U8 d. C5 s: r3 x
  105.     foreach (var sourceFilePath in files)" R2 O# @. |' c5 I4 ~' V) Z7 |
  106.     {
    6 e: {( u% ^2 `: [7 e) x
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    % Q# ^2 O0 _9 Y) ]3 I
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);& j$ u; p; G9 ?+ C/ E% s2 O
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");6 w4 \4 O( l+ \- e/ M/ i
  110. " S/ z4 a/ ?1 w& ~
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));0 z. I% o2 w" C9 v9 }# i6 x) V
  112. , f* M9 K9 d, |' M% k

  113. * u: W) x9 v9 e7 d( \4 h
  114.         if (!File.Exists(destinationFilePath))- @/ N6 R; I. O
  115.         {% C) L3 U6 B0 b/ M
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");3 ]( N4 i: R! }# C) i% f

  117.   x9 d- x; ]. u2 F: z5 Q# W
  118.             using var fileStream = File.OpenRead(sourceFilePath);0 z' f: T  h- M5 p4 i. J/ K
  119.             var segmentIndex = 1;
    - g8 \4 T) V0 F- z
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter
    ' t2 s' B5 c8 W* }
  121.             var startTime = DateTime.Now; // 记录开始时间
    ' A3 h. }6 D* @: s. A! k
  122. : I- P0 X1 {5 F5 [  U% N  O4 x+ A2 p
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    & `4 X; A; g9 m, D( B+ g& i
  124.             {$ ~) g, k* |1 W* b2 e( z" C. H
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    6 S# L+ _- U$ a4 |; I, ]5 {1 w
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");+ S& E6 ^; S, {0 J4 _
  127.                 Console.WriteLine(segment.Text);9 Y+ A/ J! u' g+ M
  128.                 Console.WriteLine();
    % A) J2 {) [) R8 i3 u6 h, B

  129. $ U, X( J- F; T2 c3 S
  130.                 // 将srt内容写入文件0 _( D; `( r" e# }7 E$ ?: |/ p
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");! y& E) @: }6 B9 h0 F1 f
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    # f1 e$ C  T# i8 V
  133.                 await writer.WriteLineAsync(segment.Text);: z+ s& y7 M8 c' h7 ^/ ~5 F3 ]
  134.                 await writer.WriteLineAsync();' `( B( x9 r( u) p5 u) p

  135. ( K5 b# f' f" B5 q3 L, x# a1 H
  136.                 writer.Flush(); // 立即保存srt文件' I3 y4 F9 D9 v- ?. ~
  137. $ M& D- x- q0 N3 ]
  138.                 segmentIndex++;
    2 j. s; k  ]: T: K2 v5 r4 e7 A/ U
  139.             }
    1 _+ m- r: r" x3 {6 i! t: Z& b
  140. 8 f- j/ M6 f7 L  B  _! U
  141.             var endTime = DateTime.Now; // 记录结束时间( `' d: R5 C. o. ^7 v: f0 @4 G
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;  ^6 n3 w% _3 w* ?2 W
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    & T2 o) K) M7 u# T
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    : N( I0 _  D' [$ ^% i" U/ G5 `
  145.         }
    . M& l1 I+ J" V9 _
  146.         else {$ I7 l! v  o; D7 a0 W7 B
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");
    ) v/ b1 W& H7 N, t% ]1 Y! N% |4 s( ]
  148.         }
    - q/ Q+ c* Y6 F+ y
  149.     }
    ( u2 y  f( [8 P. q, M
  150. }
    . M5 n+ ^% K: z+ K9 E& U, `
  151. public class Options1 g  e' H: o- T* ~1 i; w
  152. {
    % x. `4 s- i0 e0 q, c
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
      y% _( A$ M7 ?! E( d* ]. S) d
  154.     public string Command { get; set; }
    ( J% @; U7 k) ~, N7 A$ G

  155. 3 |4 {- r) f# h; ~( N/ G
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    7 w8 u" k: \6 h; M  e' N9 M' R
  157.     public string FileName { get; set; }
    ' x+ e3 S1 y6 h. `, R8 d6 n

  158. 9 f( [( Y; J1 R8 l; y" F; N$ f
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]& R# ~0 N0 f: `6 d$ c9 }; Z
  160.     public string Language { get; set; }
    - k5 H- I9 t! R" j
  161. $ b9 q# z  W8 H6 N* W
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]
    6 f1 U2 C( ^: e0 y: Z
  163.     public string ModelName { get; set; }
    ! g, C1 b' i$ [1 W
  164. ) I, D0 \4 Y, ?$ i9 O6 t
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]# K, m/ W9 E  g9 ^; Q* ]
  166.     public GgmlType ModelType { get; set; }9 h, l% _. F) |- F9 L( A7 ?0 f+ n
  167. }  P8 r* t9 w6 {/ [
复制代码
1 x" a! n8 r2 S* F

. J% P" Z2 S1 b$ |2 l* o7 H
  z: ]) Q  {6 l; g4 b% r, X4 {; u

作者: 星之韶华    时间: 2025-4-4 01:06
学习学习一下




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2