设为首页收藏本站官方微博

建议 【汉化工具系列 #2】指定wave格式转换为srt格式字幕(CPU版本)

[复制链接]
查看: 608|回复: 0
打印 上一主题 下一主题

[建议] 【汉化工具系列 #2】指定wave格式转换为srt格式字幕(CPU版本)

跳转到指定楼层
楼主
发表于 2023-9-4 11:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

【汉化工具系列 #2】指定wave格式转换为srt格式字幕(CPU版本)

本帖最后由 shane007 于 2023-9-4 12:57 编辑
; f6 C4 D. @. j& s  b+ W
0 e/ R" `1 F2 T" {2 U- b 本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,4 h& B) |# A( ~/ J: Z5 T$ l
使用时需要輸入语言,源文件路径和目标文件路径3 K1 Y: X5 R* G' e
最后是输出srt文件+ B2 d1 N' q: e1 H+ m& V

8 R$ ~6 j" b4 x1 V: r8 @代码如下
9 c4 G$ z$ C! A以下这句用多线程可以增速,否则很慢
. c! ^0 C2 A4 ]2 ?以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。
  y; _' J, a6 s0 E, Z% S& w& _: ^
- M3 e+ E+ }0 Q* h# n: n. K6 b# y% u+ U9 h3 ]& l2 p
  1. var builder = factory.CreateBuilder(): F2 L% N8 |: Y, e) b; @
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码
" d4 Z$ C' j4 [5 V( f
& `# N( x4 ^+ C* s/ ?8 b  p; @
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT
    2 x% E, x# m# e1 h' C- G

  2. % i. g4 f2 U2 h% i5 J# f
  3. using System;' Z) V& p( \- M% W+ f; y
  4. using System.Diagnostics;. r7 r9 @' U8 t1 K
  5. using System.IO;
    , Z" i! F4 t$ ?  Y5 ]1 @  y
  6. using System.Threading;
    2 v' j) j& h0 [( A7 _
  7. using System.Threading.Tasks;+ V, b9 p) u, A: h! j
  8. using CommandLine;
    9 U! o3 `, \- F# w3 L* q6 i2 M1 ?
  9. using Whisper.net;! C+ i6 G# k& a
  10. using Whisper.net.Ggml;9 [( j: w  N; Q, V* U  P
  11. using Whisper.net.Wave;
    / @1 N7 c: C( ?9 F6 o
  12. ! P" ?; J# Y5 h+ k' l6 `5 ?
  13. await Parser.Default.ParseArguments<Options>(args)
    / V2 _* @9 \% @  C$ V6 [/ p* p
  14.     .WithParsedAsync(Demo);
    / c; N1 l2 \- H: D/ }+ f

  15. 1 u$ Q& B! B' n
  16. async Task Demo(Options opt)3 Y/ d/ H7 W. P

  17. ( M7 j! K6 V# L2 C  o# t
  18. {
    8 ~( y2 c* p6 Q4 _* n7 L& [
  19.     if (!File.Exists(opt.ModelName)): M, B1 e4 \2 P1 L. \4 X
  20.     {. I) Y, z* c% y# o
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");9 e4 H6 F. R; z# u8 C
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);
    & B% B, {: y2 W/ X  m8 x
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);2 J' `- W5 W, M% l4 T( d; g
  24.         await modelStream.CopyToAsync(fileWriter);
    ) a8 X) |' X8 ^! h, @0 l
  25.     }
    & M5 Q& ]- y3 g; i. S2 C0 m

  26. 9 m& S0 u& m" @0 t7 g3 K$ r
  27.     switch (opt.Command)
    % D" d' i: f# T; ^' i5 v+ r  h
  28.     {
    / i- B# y& A, r! O0 u
  29.         case "lang-detect":: I% ^! ?3 x  o1 }" d9 r" R: `
  30.             LanguageIdentification(opt);, d3 S& q: ?9 e9 J
  31.             break;0 c* y, h7 A4 }  t4 Z
  32.         case "transcribe":
    / Z% k3 v& ?( I% t5 ^5 s
  33.         case "translate":$ F  E' b5 M# \! y2 q+ `' O# S
  34.             await FullDetection(opt);- _6 Z. q; ~/ w$ R
  35.             break;
    5 ]0 s8 I1 Z3 H! z0 W
  36.         default:
    ) U1 q% C7 y. a: w4 J
  37.             Console.WriteLine("Unknown command");
    ) F4 m+ [0 r) r; C$ B/ l% i3 B7 i6 V
  38.             break;
    ! l  H4 T% @0 E4 F0 k, s
  39.     }: y4 U# C" U' m; R  Z* b
  40. }
    * D* m$ u! E( K
  41. 9 r# g- A* k' Y* n
  42. void LanguageIdentification(Options opt): }% k, ]3 C" @, y: k
  43. {3 B9 ^/ m7 X2 Y# }7 k. i' B
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);+ Z9 O" k1 P& Z& ^$ e( a3 c: Y5 I
  45. / h4 o0 w5 W. k: r$ z2 Z
  46.     // Same factory can be used by multiple task to create processors.# n: `' E: N: ?4 @+ c: i+ [
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);
    - M+ G& R" Y* d1 t0 w

  48. * H  I7 e, W4 f) s" Q
  49. /*    var builder = factory.CreateBuilder()
    ' d0 Y0 D- D3 F4 r! f' y
  50.        .WithLanguage(opt.Language);*/
    . H, U1 q4 ~0 y* F1 D3 H- R$ s
  51.     var builder = factory.CreateBuilder()
    , u2 H/ j4 q, c( X6 y% [- G* ]. I. i7 H6 q
  52.    .WithLanguage("english");
    ! b4 h) C- ~" E
  53.     using var processor = builder.Build();
    ) P4 H  L8 }" \# U

  54. 0 V) b1 l, {( w* L  q
  55.     using var fileStream = File.OpenRead(opt.FileName);3 C) k0 F- m/ L0 X& A0 m. S% _+ B
  56. 8 u! t3 S0 m2 k3 ~' Y
  57.     var wave = new WaveParser(fileStream);& f6 m( l9 I& s$ u. S- B3 O

  58. ! g3 {/ l' p+ I
  59.     var samples = wave.GetAvgSamples();
    ' p' Y- P" W; B0 ^
  60. + p: S; T, t# B/ Q/ s8 I
  61.     var language = processor.DetectLanguage(samples, speedUp: true);
    7 q* N0 n; W* F- w# O; Z- K
  62.     Console.WriteLine("Language is " + language);
    8 g1 J! T1 r: h
  63. }
    . ~( W9 m  n% R* ^, C0 \' G
  64. $ E) T6 o" d6 `; Y
  65. async Task FullDetection(Options opt); p" R9 k- w/ f1 `! I$ T7 ]# D
  66. {
    6 e1 D) S$ `0 \
  67.     // Same factory can be used by multiple task to create processors.
    / p  _' |) s5 l8 O
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);
    . G. Y4 ~- \7 l5 y' V" Q

  69. / F6 f. A  O5 z, A: m- j9 ?. j
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);$ |5 s0 K2 @, H: r
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");
    / @3 L" W4 M* t( y
  72.     string languageOption = Console.ReadLine();
    & F+ I  I- M& I1 Q: N% \
  73.     var builder = factory.CreateBuilder()
    7 S4 X7 E5 p) v# d8 x( k3 F0 P
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);1 k4 X9 `+ A5 L) N
  75. ; n/ U2 s. v6 D7 u
  76.     if (opt.Command == "translate")
    ' {  h9 E6 I& B7 \0 C3 |6 H2 w
  77.     {
    / T6 Y: t$ @" ~; i/ `
  78.         builder.WithTranslate();- r1 J" d  B1 Y
  79.     }
    & ~7 [& ^; S8 [9 t. ]2 r6 `* B, x) l* ]

  80. 1 A5 r5 v$ e7 E9 W3 z$ q' M4 D
  81.     WhisperProcessor processor = builder.Build();
    : I* D  S  f0 S% S, h% L
  82.    
    9 A+ r! w% a' ^
  83.     Console.WriteLine("请输入wave源文件目录:");6 h6 A9 ?& Q7 A* K1 V
  84.     string sourceDirectory = Console.ReadLine();
    5 D2 V# y7 u1 i

  85. % M9 h" C  h6 r3 X$ S  F
  86.     Console.WriteLine("请输入目标文件目录:");
    % P1 z: K9 c  X" \5 L& V: g
  87.     string targetDirectory = Console.ReadLine();* S- u  S& ~  u8 U0 n. U- a

  88. " L' o! r: I- T. G
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    - `7 Q0 ^- X6 c
  90.     {* \' ~* u; r. E' t
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    # C% r4 T: [3 H' k1 L
  92.         return;
    9 t) g% B0 b+ O/ P2 J
  93.     }
    % t) j! T/ Z" O

  94. 0 l1 w1 D& j9 s
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);
    4 E. ~9 \1 G. z! M/ x4 a9 b

  96. . T# j+ u; x/ @, ^
  97.     Console.WriteLine("处理完成!");: d; g0 N1 E; Z  Q4 L% K
  98. 3 M3 \: f0 _: Y
  99. }4 H9 O/ E* r- }  @1 p
  100. static async Task ProcessFilesAsync(WhisperProcessor processor, 1 @9 V! [* N$ H' ?" h% j
  101.     string sourceDirectory, string targetDirectory)
    # X3 t9 W( Z7 V$ z
  102. {
    # d. i2 \+ V: N- k' ^# s( c
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);/ z. I# f2 M; Q
  104. ' O" A: d0 U3 F  t
  105.     foreach (var sourceFilePath in files); q: n3 |% o4 G4 N1 R) t, y
  106.     {! j! S- t' l0 m8 R- s2 T
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    2 J4 ^& R4 ^# g& E/ i
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);
    - m5 _4 D+ I9 `# n8 D8 s
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");, l* M' o  `: I5 s& K/ m

  110. ( o! E5 m" j* w
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));" J, n$ O5 g+ ^8 y" B" W# l3 l

  112. 9 v" K" b* l" L. V/ a* N  F- E! P

  113. ! ]9 v2 M0 W/ A
  114.         if (!File.Exists(destinationFilePath))& f- _/ @% ?) M  z: {; ~/ {7 H
  115.         {8 y% P5 u- O* {% C" G* M9 X# R' v4 A
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");* N* m' y+ N0 O3 N: \6 E
  117. ' R2 [4 D- m4 Y( P5 M+ r* ?
  118.             using var fileStream = File.OpenRead(sourceFilePath);
    + K1 R6 Q3 X! m. j+ Q' o) B
  119.             var segmentIndex = 1;/ Q! O" [+ b# x% o: ^) v
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter
    ! X1 V+ N* x' B& g0 c9 m
  121.             var startTime = DateTime.Now; // 记录开始时间
    % T( D. r1 P3 [

  122. ! H5 ~3 j' r* ^/ C$ C
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))7 b# [- f3 G4 O  G
  124.             {" ?2 @; d! D7 t) s( k, W
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    ( Z1 S( Y$ W$ }: f; \
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    . _2 O7 m( u% A5 E
  127.                 Console.WriteLine(segment.Text);  ]# l8 b" b# ]
  128.                 Console.WriteLine();, R2 Y: x' R9 ]: h6 {
  129. 0 e; z9 R1 f1 Y
  130.                 // 将srt内容写入文件
    / B9 A* r: I& D
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    # c: G4 {' h$ v6 b& j5 }* |
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    $ Z; c2 L$ p' O) o6 L  N2 ^
  133.                 await writer.WriteLineAsync(segment.Text);5 f0 J! @7 J7 d" |7 j
  134.                 await writer.WriteLineAsync();
    * q: u4 [9 S) F

  135. " L# |1 `( J; y# R
  136.                 writer.Flush(); // 立即保存srt文件1 m, H- L! }% B4 s+ x4 G

  137. 3 G  M- q0 V& i3 w5 E
  138.                 segmentIndex++;
    - j1 ~" ?( S9 V+ C0 {* r
  139.             }: I/ ~4 @, U/ b
  140. " A) z7 B6 `  z, \9 I0 B
  141.             var endTime = DateTime.Now; // 记录结束时间
    ! m; Q% m( ]# Y5 g4 B& ~/ k( e' P) e
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
    2 ~3 b0 y* o1 c
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    * n9 b& y0 i, L+ w3 ?* j2 p5 p
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    ) q; n* T8 B( K) @( s0 D- w
  145.         }
    1 U: f, w* y7 o0 V, W5 h( ?  y
  146.         else {! Q, @. i( {" y8 y, y) F& G/ I
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");
    , t% f5 }, ^1 A1 `3 w! D  Y9 Q; o3 V
  148.         }& I: H: f# A. h% k
  149.     }1 L  J1 Q/ h' @$ h' j, M8 H
  150. }. Q8 m; Q: y6 T5 @, J1 {+ M1 O8 ~
  151. public class Options
    . y5 S' c3 r) I  a
  152. {9 v' F+ _- X0 T" f6 i' n
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    * Z2 ~, P0 k( A  I8 M, r* |
  154.     public string Command { get; set; }
    . S# P) e( E) y2 R. Q9 e1 \- Z

  155. ) ]4 T1 Q$ T: a; w' G
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]# ]$ ]: n/ f7 ^' Z6 F4 g2 i8 h
  157.     public string FileName { get; set; }8 x4 b" `  T) D
  158. . O" @% j: H2 ?) V* P# n7 F7 _
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]0 e2 W2 S' A, K( j% t
  160.     public string Language { get; set; }+ j9 u9 K& l- X

  161. 1 y; @4 z6 m# x, g8 j) I6 A
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]
    2 ^. S  s" y+ M% n' ?% D
  163.     public string ModelName { get; set; }
    " p0 r! m, S4 P- V& W

  164. 2 J  U+ @; u  T4 }3 @& K+ p
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]& ?; b9 K: I9 u" O
  166.     public GgmlType ModelType { get; set; }9 G- X6 k& j9 h" g/ l
  167. }0 Z1 _' @. f+ g0 L3 Z6 ?
复制代码

0 z* X0 d9 x2 e& n3 l: H
( ^' i! R4 G" @6 y8 c' I+ @6 g4 V* K: \5 s& o( K' S

  N4 i' ^; d# u" @" C
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表