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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑 . V  ^2 G0 k7 ]1 y6 m
" v$ L+ a% n, |! n
本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,) f% N- K, O' U; T( [
使用时需要輸入语言,源文件路径和目标文件路径1 J/ D; h+ E( K3 d  d) A2 g
最后是输出srt文件: J0 b0 K5 l+ L/ n2 r& r( A! j0 U
/ j& x5 l2 |- f  F& r( {) a
代码如下6 o3 X' B, L: I: `: N% a  }
以下这句用多线程可以增速,否则很慢
1 r, ^( c' @( y" l( p$ _以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。2 Q) r5 ^$ `4 ?9 O. ~0 V) t+ j2 h

3 s1 A$ A5 i0 @/ N* _# |0 f& T2 g% G: N2 A! b3 c; J. H' @
  1. var builder = factory.CreateBuilder()
    * w/ q9 r! ]3 v% E; @0 x& r/ ~" {) l
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码

5 H( f, h' q5 C2 n. A* `" l0 ^
$ s) g/ P, M( j5 ^( F6 @( n. X
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT7 F5 _  V$ @' J9 }: H
  2. & k9 ]- }, G% P) H, B3 F$ F
  3. using System;& o7 y6 s$ g% w+ K1 K* F3 q; e
  4. using System.Diagnostics;
    " B, R8 V9 j! t
  5. using System.IO;
    - F5 L' h- _0 u7 I1 q% z% y& q; l
  6. using System.Threading;) `$ ]6 \1 z' ?' a: Y
  7. using System.Threading.Tasks;+ @3 P3 w. |7 D) {+ N! _3 c
  8. using CommandLine;! z9 M( p; }0 @. M/ M& ~
  9. using Whisper.net;
    9 [  r, a5 G. b7 i2 |
  10. using Whisper.net.Ggml;9 h/ D7 L" w# a" Y5 ]( I% P
  11. using Whisper.net.Wave;
    / W# [7 Z. f! W2 l7 j7 ]4 u

  12. , e) M2 y) [# g' S1 w$ ?) B
  13. await Parser.Default.ParseArguments<Options>(args)
    ' N1 Z+ `+ A" W
  14.     .WithParsedAsync(Demo);
    - T; E+ o; K( y$ H; e, _8 q/ e  E
  15. , y& f7 I0 e1 h% ]$ j+ |0 U
  16. async Task Demo(Options opt)
    " q" z$ X- V0 A( X4 {: o( g/ ?
  17. & Z" t6 F' J) O' p
  18. {0 A4 K' q2 ]. n; _, [2 Q8 [
  19.     if (!File.Exists(opt.ModelName))
    / G  ^" Y/ v. z0 T
  20.     {4 L. F1 i* r4 n( _% b
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");: h& ^% \2 I7 j; K. b$ `; A
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);5 T/ \% R- R5 v# p
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);
    : D' {9 [6 Y6 Q' s: P( D, U4 I' N
  24.         await modelStream.CopyToAsync(fileWriter);
    % j# h3 |3 ^7 r8 S! T; h+ L  c
  25.     }9 G6 E: r2 V  r5 }( E1 j4 H

  26. - B# |  x8 C# G5 F; \: T
  27.     switch (opt.Command)
    ' X) U9 w  ^0 h5 F, O7 w/ q
  28.     {$ a+ `  d: s( L3 Q
  29.         case "lang-detect":( I; U4 R0 Q4 H2 |2 t. h
  30.             LanguageIdentification(opt);) _; E! U4 M: j' D" i3 N! h
  31.             break;2 w3 J# V1 E( b3 z# Q/ a/ i
  32.         case "transcribe":
      I( q8 n  n+ ~* i
  33.         case "translate":
    ) n9 @5 n2 v3 u
  34.             await FullDetection(opt);
    , |3 P2 c+ L5 J/ t2 [- |: C* Q6 t
  35.             break;
    : R$ Z) x0 |1 G4 L- N
  36.         default:
    6 z2 |2 N- }, O0 @$ \
  37.             Console.WriteLine("Unknown command");
    . X* O/ j3 a' x; k9 w
  38.             break;
    3 K2 M0 k" O, Q: E/ W
  39.     }
    + M" m. ]) A, O1 y% U  g0 E
  40. }
    ; ]/ F  D! {+ r; f6 y& U, B" |+ S8 R

  41. 0 O6 m% h% q+ N, P* a9 |- Q
  42. void LanguageIdentification(Options opt)) T7 p' T1 s6 }6 g) @/ {& F
  43. {
    * O: K- ]( O/ i0 @0 {, ^
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);
    % x  }/ |+ w$ `' \7 {- p( l

  45. 0 c; v! y' @0 M/ J1 E0 a0 P
  46.     // Same factory can be used by multiple task to create processors.* l' E" N5 d; j, s3 W
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);" c1 X$ t: v7 h0 l1 H2 H
  48. : V: ~4 q' e7 _* z+ d2 J: \
  49. /*    var builder = factory.CreateBuilder()
    ) ^0 {3 h$ D) E: B4 n2 ~
  50.        .WithLanguage(opt.Language);*/3 z, v) E+ d$ p! z: H5 a, F; u
  51.     var builder = factory.CreateBuilder()
    ; k3 U" n' z# e. _( O
  52.    .WithLanguage("english");
    / D6 v- b" y# L4 f) D5 `; t- j" n
  53.     using var processor = builder.Build();4 _5 ~7 d( t) n/ m

  54. 6 }8 d, V- L/ A. _. F
  55.     using var fileStream = File.OpenRead(opt.FileName);, U, [$ n5 Q. j2 _! ?
  56. - s3 k: ?* S1 L
  57.     var wave = new WaveParser(fileStream);
    : q/ @0 Z9 w1 J( [% c0 `) ^

  58. # L2 a; L. _* d4 r
  59.     var samples = wave.GetAvgSamples();; D* U" h& Q! n1 s% J9 U1 m9 h

  60. ( \; [4 V3 a, h9 N; e. q# W3 i& j
  61.     var language = processor.DetectLanguage(samples, speedUp: true);7 P" p8 s/ j- w. F0 q
  62.     Console.WriteLine("Language is " + language);2 x4 i3 j5 @. v4 {* ^+ ^  R
  63. }6 S7 V% o! b2 k/ _) `( {( n) S, c

  64. ; t, m" [; o' d* E' e5 N
  65. async Task FullDetection(Options opt)
    6 W4 g+ f# o1 _6 d' w: N2 [5 A2 }
  66. {
    " V* y4 s) }- i& s7 C) f/ E
  67.     // Same factory can be used by multiple task to create processors.+ u7 X5 ~: I4 X8 ~7 N; r. B* |
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);' w3 L; L! a! \) J/ `# G3 ^0 b7 T7 w

  69. : n) s  t% D4 P/ R6 \& r5 b
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);% e- U0 \0 w+ L& u/ y/ E
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");8 h2 W6 d, y8 F0 d! t
  72.     string languageOption = Console.ReadLine();
    2 R3 b" I* u! R1 j5 {: Y
  73.     var builder = factory.CreateBuilder()9 \6 x6 ^: c' ?6 c8 J
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
    1 v7 @$ F8 c. h1 A# `
  75. 0 A$ u' y" v& O+ J+ r# _
  76.     if (opt.Command == "translate")9 N+ P  f5 Y( a8 U. {* W. r
  77.     {
    + S; S; e. U' s# O8 r; s
  78.         builder.WithTranslate();9 P2 [4 L/ s  J  z4 ~
  79.     }
    5 g$ ^0 }0 X- F+ v# p' e8 Q3 @9 s

  80. " i  B( q) V2 {, Q' `8 o1 H) H
  81.     WhisperProcessor processor = builder.Build();
    ( s; S2 M, x9 y- `- v& }
  82.    
    & @- B2 L! S: T; N
  83.     Console.WriteLine("请输入wave源文件目录:");
    4 ^" }% c, `, p( g
  84.     string sourceDirectory = Console.ReadLine();+ |: b5 Z9 U# ?
  85. : s% I& H- a6 S6 U+ d; b" Q
  86.     Console.WriteLine("请输入目标文件目录:");8 W7 d; ^- E8 D1 o  A2 m4 l- W
  87.     string targetDirectory = Console.ReadLine();% e7 V9 }# W1 M% L
  88. 8 V! N0 f1 a8 Z$ p' _: Y8 `1 ?$ g4 R# Z9 O
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    & b0 x/ f- [( ~. \2 k
  90.     {
    + S7 w8 w  l8 d+ |+ b
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    , p7 Z0 H6 d& a* b0 Q  z
  92.         return;* Z* N& f! x( K: O  g
  93.     }" Y5 t$ h, W) P- E% x2 L1 z
  94. & P: F& F  N" `) H
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);
    " u* T2 k( N2 j! b' O9 V, a4 {: v

  96. 1 a8 B$ z- u8 f6 P& t0 Z
  97.     Console.WriteLine("处理完成!");$ _$ d* g" Q9 d9 v5 h5 G; L3 g0 ]/ ]
  98. 4 F2 ]' \. L; T9 d2 K8 v( \7 {6 @7 }
  99. }
    9 E* V2 i+ W: G  C8 U) a
  100. static async Task ProcessFilesAsync(WhisperProcessor processor, " W  k7 K$ |- ]% d& |+ K; x
  101.     string sourceDirectory, string targetDirectory)" M( j! o" Y! X  i( [# j- Z
  102. {; {2 a9 Y8 }; ]/ ~' X% T6 A5 c  s5 U2 L
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);
    # t. _* y7 O7 R1 R4 ~2 h& ?

  104. 3 B' l2 T& K8 O6 n* o
  105.     foreach (var sourceFilePath in files)
    & f" I2 S) S% `
  106.     {; Y6 r$ j  ]& ~! Z. Z3 @( f8 L
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);6 I4 m: p. ]. Q; L
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);
    . b' o3 C4 l& D7 \! R! |  x
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");
    5 h. @9 N- m6 v6 S
  110. ) k) [: H: Q9 i# {' ^; M
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));
    2 ?" U( a$ N1 i$ U0 a
  112. * P0 c- Q  e" m/ r* H
  113. ; g% Z5 D% g9 o! l; x
  114.         if (!File.Exists(destinationFilePath))) v5 O* q9 @& {, X) `
  115.         {' H* {. @/ z6 N. a6 W% Z. p& P/ s  M
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");0 z6 A# a! X/ U

  117. # \* y: @/ d/ O7 s7 e* x& n; k
  118.             using var fileStream = File.OpenRead(sourceFilePath);
    % W! m# r5 m2 ~9 u$ K
  119.             var segmentIndex = 1;
    : |* ]1 n! N* p1 S9 g
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter
    " t! T  Q5 s/ b- Q0 {
  121.             var startTime = DateTime.Now; // 记录开始时间/ F% j1 a& N9 y# F, X* E/ X

  122. ! S/ L& q: H6 r" n
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))6 t+ B& [' b4 i2 e3 H8 J
  124.             {
    ) H1 U- R6 @: ~1 s) f* c
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    3 `, {( H% G" {3 @5 h, b
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    7 W  X0 O* d" a
  127.                 Console.WriteLine(segment.Text);
    % J( ]9 W1 Q' T, x
  128.                 Console.WriteLine();. s+ e* x8 p$ a+ J: a4 x$ ^8 o& A8 t

  129. ) P: H. k$ n8 {9 ]) P2 P6 S1 b8 D
  130.                 // 将srt内容写入文件9 o* y4 {3 W& \
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");/ l& i$ Y( F! \! B1 x
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");' n7 o/ \3 l; E) a/ _/ e
  133.                 await writer.WriteLineAsync(segment.Text);
    $ g- E5 U, d. x3 p
  134.                 await writer.WriteLineAsync();6 B6 I3 ^) J! |- p
  135. ) c# ~- l2 n# ~' _7 J" G
  136.                 writer.Flush(); // 立即保存srt文件
    6 y2 T9 T) z: Q+ G; b

  137. ! Z, y$ y1 T) ~- v6 z, Y1 y5 J
  138.                 segmentIndex++;) I! M! m/ L% J, K
  139.             }5 q$ m& X' Q1 C8 I- ?% k

  140. 9 e5 r; l, |) R$ Y' d  e7 v
  141.             var endTime = DateTime.Now; // 记录结束时间
    % x4 N8 n% J1 o
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
    9 l$ Y$ V2 w4 E: U2 {' |' g
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");+ o- Z; X  f- C) x! z
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    ; w8 G; p; |. n, N
  145.         }
    " B8 ^3 B$ p- }- F% y
  146.         else {
    ' v! j% n2 I) U/ B# E# L# T/ p# g
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");
    3 x4 p/ n. w) N+ e
  148.         }1 F% V4 I% q' }  L
  149.     }
    $ `/ A1 Q6 l$ E+ Q2 x" `
  150. }
    ! |/ T5 P  G" g$ N  Z
  151. public class Options4 }/ w: J% Y9 X& E8 ]
  152. {& }! _- V- W* L2 k5 J" n8 ^. g; c
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    6 F/ B# d2 w# ^  x; h' m- b
  154.     public string Command { get; set; }4 ]: l# ^2 l6 ]$ I

  155. + \4 D/ X' m" S6 \# k+ a/ `+ T
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    8 @; B. K  {( Q' q' H
  157.     public string FileName { get; set; }
    , `# f; f) ]; Y3 O

  158. 3 u* E) w3 E' _
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]
    7 I4 A& U4 k% T
  160.     public string Language { get; set; }6 K/ F- e* Y+ R! k

  161. ; q& q6 V% M, X7 z
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]
    4 z+ o8 v: ?- X' D
  163.     public string ModelName { get; set; }: O( E! {, x6 }

  164. 5 x# e2 f, Z: |( f# V) }- u5 |
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]
    5 ^" e$ T, C& m2 Z% u
  166.     public GgmlType ModelType { get; set; }" f3 |2 B/ }2 o8 j7 a8 P7 }
  167. }. v, l: |( U- g
复制代码

! W1 G- u+ X( Z# I4 \$ o. k
* y/ k9 Y" o8 C$ m6 T  }, h$ z  ]# [( S) ~

7 S. T' A7 O( a+ V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2025-4-4 01:06 | 只看该作者
学习学习一下
回复 支持 反对

使用道具 举报

高级模式
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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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