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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑   Q8 z. C* k5 }% B& W2 }

) Z2 w; k8 E7 z2 Q3 c! b0 c 本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,
& c& f6 C5 o* S# N 使用时需要輸入语言,源文件路径和目标文件路径0 @0 ]# _& N6 v; ^- {6 s
最后是输出srt文件
' O9 y7 ]1 J) _8 |2 w% s% v( X1 s, j) d( d) s: S0 ^0 Z
代码如下( F& E1 h; k9 J
以下这句用多线程可以增速,否则很慢
! H, Y: B- t8 Q# J7 h以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。
! f% s4 Q5 n3 G
. U" m* p! {' l( b0 D
- Q" W0 A+ X" `6 Q2 {
  1. var builder = factory.CreateBuilder()
    $ u) V& X+ |+ n3 p' z
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码
, j( c9 P5 ^! }4 U) f# {- Z( h: n2 ~* M
% U7 m$ p/ \$ T
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT+ y1 |! W0 z5 t. h

  2. 4 \: l2 R' o( Y7 G3 q
  3. using System;
    & z8 K3 R* L: y" Q  v, h6 H" L" ]
  4. using System.Diagnostics;- J1 n% D3 s7 y. s
  5. using System.IO;5 `3 I: I+ M- Q" P; H
  6. using System.Threading;* x$ C1 J$ x: g* A+ D
  7. using System.Threading.Tasks;/ k7 Y3 C3 Z9 v8 o9 o) |
  8. using CommandLine;
    1 f, R6 Q# P* ]: p, C. Z- R
  9. using Whisper.net;' @( g1 f. [, o2 a$ p* V
  10. using Whisper.net.Ggml;9 Q& C) f% u5 B, }) O
  11. using Whisper.net.Wave;
    % k( v& N. o. T8 E& M7 X0 |- j  \
  12.   Q4 w( E1 h. I2 l
  13. await Parser.Default.ParseArguments<Options>(args)" {$ Q; f' O+ E, |- s# w
  14.     .WithParsedAsync(Demo);
    ' J0 M2 W' C6 o( C$ @8 y
  15. : B( U% e. K; W8 ^" ^' y+ ]
  16. async Task Demo(Options opt)
    / K4 i+ Y6 n3 C/ I
  17. 3 l& Q+ }( ~0 }, T  u  V6 Z
  18. {4 {0 t0 U7 [& l# V# @' l$ q6 V
  19.     if (!File.Exists(opt.ModelName))  B( D, ?* Z/ @. b$ w/ @  I$ G1 M2 k
  20.     {
    2 w5 N/ S! ^+ X9 }. k" m8 R
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");
    5 B$ \3 ]0 `( z/ P2 h, m7 q
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);! b) T5 K+ T& a+ E3 F2 d) Y; G4 R
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);
    5 B9 {4 X' ?; R9 x5 C
  24.         await modelStream.CopyToAsync(fileWriter);
    ; d: ]0 y  n( x2 U, P2 n  i
  25.     }, E, A0 R. e1 ]
  26. 1 W. @, `6 L7 ~6 o
  27.     switch (opt.Command)8 }  y- k2 l8 j4 r
  28.     {+ x. \  a! B; e
  29.         case "lang-detect":
    2 f6 H0 E2 i( J
  30.             LanguageIdentification(opt);- {) ]7 w' G5 Q
  31.             break;) l* E5 F9 r1 i
  32.         case "transcribe":: Y) |3 O4 m) A1 k
  33.         case "translate":
    2 D3 o7 Z) X- p7 b  n+ z
  34.             await FullDetection(opt);$ x7 G( S; f. n6 \# `0 n9 p4 T
  35.             break;
    4 ~) ~8 c: Q; g
  36.         default:
    , H- Q+ J/ a' {, {3 E6 D, ~
  37.             Console.WriteLine("Unknown command");
    6 k; ~, \  S/ E, J9 L
  38.             break;. u0 n# t9 ^! H* \. k
  39.     }' t2 j$ N1 _( [, D( k, Y# K" L
  40. }' }: |, e& R! z* a
  41. * O6 `6 c! M' ^4 }6 ]
  42. void LanguageIdentification(Options opt). \" _/ P+ R* Q, b* I
  43. {5 l9 O$ N9 H) \2 Z$ C) e2 t+ g
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);, B) E- x7 G! m8 P

  45. 1 t7 z8 |! c, l  w5 D
  46.     // Same factory can be used by multiple task to create processors.6 L4 O: c; s" T1 j  l1 h
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);
    + l/ X/ a( s) Z/ M* F$ W/ O
  48. " f, x1 A" `! s9 [8 F
  49. /*    var builder = factory.CreateBuilder()* W3 Z, Q; ]2 x
  50.        .WithLanguage(opt.Language);*/7 g4 w* F) l4 e( H, l) j* b
  51.     var builder = factory.CreateBuilder()6 k; Q% R6 ~" f  r5 @  f* k
  52.    .WithLanguage("english");3 z& x9 h) o7 i; a# w% t. L
  53.     using var processor = builder.Build();- R  `  s: b. F. S" m% E
  54. # ]3 A$ ]/ g2 |* i
  55.     using var fileStream = File.OpenRead(opt.FileName);
    8 c9 Z" j; }1 R/ D8 b# j  ?

  56. - q6 S4 U: n6 f8 z3 P
  57.     var wave = new WaveParser(fileStream);+ }- W# F# g7 S1 r+ a- J
  58. 2 Z8 `, V' A8 W' ~% z. W: W
  59.     var samples = wave.GetAvgSamples();- Y, r5 i+ g* ~
  60. ) W; Q+ i# o! d( [1 O$ u* \
  61.     var language = processor.DetectLanguage(samples, speedUp: true);
    1 g" Q$ W( ^& M, C/ }: i: @# G
  62.     Console.WriteLine("Language is " + language);
    & X, L% y0 P- k( k( G; l
  63. }1 `6 p7 V: @. O% Z! |
  64. - b& z+ v7 z: k8 v4 ^
  65. async Task FullDetection(Options opt)
    4 m& c# p/ M8 g/ ?% k5 d
  66. {! l8 W6 n) f$ X. d  }
  67.     // Same factory can be used by multiple task to create processors.# c8 {" I0 G0 C" X% |) F* S0 F- \
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);
    $ o7 e2 _4 C. \: M5 s  ?/ j2 t
  69. ) _, p& y- {) n
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);  z2 d3 [2 s" A% N
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");
    5 x* [/ `5 H5 J! E8 L" Z
  72.     string languageOption = Console.ReadLine();3 J0 Y- v! u! u2 X, |3 \
  73.     var builder = factory.CreateBuilder(): o+ ?" t6 L; N9 t
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
    - M( l" [: R  d4 P7 G

  75. ! \2 D5 P+ F9 r9 }" L5 S
  76.     if (opt.Command == "translate")6 W" ?- x: D- i0 T# f
  77.     {
    $ Y  ~8 X/ \7 d0 N
  78.         builder.WithTranslate();1 r1 w" K% `. y5 P
  79.     }
    6 k- r: A2 \/ P2 y
  80. 7 s8 x3 X- C# D6 v: m/ M' r
  81.     WhisperProcessor processor = builder.Build();
    # s7 J1 `  J6 p6 L$ m: F, h
  82.    
    1 A0 s7 |$ z$ N- |1 K
  83.     Console.WriteLine("请输入wave源文件目录:");
    ) E; e# }' W3 G
  84.     string sourceDirectory = Console.ReadLine();
    - P  {; A% A" x. i. Q, f
  85. ' v/ V1 l' J9 g1 P% |
  86.     Console.WriteLine("请输入目标文件目录:");
    % K0 p+ D( R: C0 y( h. |! r  \
  87.     string targetDirectory = Console.ReadLine();0 N" P" y5 `" L- l. ?* z. ?
  88. . _5 _8 J0 u% B& [+ @
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    & ]) _0 H0 v7 U6 G
  90.     {: F9 j. H4 P: U7 D# @  V" ~/ i
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    , o( J$ h& y0 o! S$ D- [) M5 h* w, Q
  92.         return;. o! Y) S% N, f9 Y6 Z- |
  93.     }
    6 Q8 `! d7 u: P" J  m

  94. 1 I# A" E0 L7 @0 S) r+ ]
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);7 A" x4 p5 @. v9 a) l, e/ d6 ~
  96. 7 C5 I! j7 Q+ K1 Z7 \2 Y
  97.     Console.WriteLine("处理完成!");
    4 k. s* y& L6 B% z7 U, t
  98. / q) W' S7 S' E! W! `4 ?3 @
  99. }
    ) J/ `, \6 C; P# C' u
  100. static async Task ProcessFilesAsync(WhisperProcessor processor, * Y! Z& r! i$ J0 N. R7 R3 J2 O% ~
  101.     string sourceDirectory, string targetDirectory)
    ( j% g/ S0 U5 R
  102. {2 r( }+ `7 Q! k1 _3 b, h. x' d
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);) m2 P' F0 W) ~1 \' n
  104. : @2 V" E0 y9 O
  105.     foreach (var sourceFilePath in files)! k9 R6 B' h) ?4 D7 f0 {1 k
  106.     {; W' ^6 r7 o) b4 [
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    " x4 \. w) d7 e: M
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);
    + A9 ?1 c! S$ b5 F7 i( H
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");
    & q# ]2 d1 u7 g7 ^/ w8 q! X% q
  110. 0 \1 }& t3 u, d& M
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));" m6 j9 x: ^: O) I  ~# n$ r1 V% T

  112. , r* n/ m9 @+ m7 _$ h

  113. 9 R6 H; L% I. u; ^( f8 D4 }
  114.         if (!File.Exists(destinationFilePath))7 z* r: O. j5 }5 ?0 v1 t2 q
  115.         {) [, q  k3 z1 D/ c
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");
    & S$ z* ^7 |& |4 i; J. ^
  117.   O: e: z" ?% L' I' J4 [
  118.             using var fileStream = File.OpenRead(sourceFilePath);! `1 C/ _  I, o6 o9 Y$ X8 A
  119.             var segmentIndex = 1;
    6 n" f+ s: ~7 o7 L7 c3 f( s
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter+ O7 e& Q9 x3 G* n) K0 j
  121.             var startTime = DateTime.Now; // 记录开始时间" m. z. N' b8 e# m2 y& D9 {

  122. 6 |" v  _3 t/ U: i6 r5 _* t
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    9 P" N2 G0 u3 Y- P
  124.             {6 \0 X% i6 g1 y7 R  S
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    2 u$ N  P9 C! |. X$ {% }6 P
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    $ [$ p  L) a$ `% B
  127.                 Console.WriteLine(segment.Text);" g/ B# B  \- F3 f8 d+ ?/ d, `2 D
  128.                 Console.WriteLine();1 Y8 @3 z/ u- L9 f- q$ ~% g; q

  129. ( c& h# E$ b9 ]1 @, `+ H8 U
  130.                 // 将srt内容写入文件  a7 b  P9 B' n) E) }
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    " a; F5 ?0 Z" E+ @2 E6 B; A( O" I  O
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");4 n$ N7 N& e# K9 j
  133.                 await writer.WriteLineAsync(segment.Text);
    ' m( Y  y) R+ r2 J# F
  134.                 await writer.WriteLineAsync();! U' D& {7 ?+ L. u, b
  135. 7 f' A8 G8 r/ ^& s) r
  136.                 writer.Flush(); // 立即保存srt文件
    , z. e" l. G3 T8 t2 R

  137. # E  h2 e7 V5 Q
  138.                 segmentIndex++;, Y1 J' z, {% m
  139.             }1 t6 M" ~* f0 s& D& k& P

  140. ' W( @5 _8 @+ j: f/ w% B
  141.             var endTime = DateTime.Now; // 记录结束时间
    . f) p7 S% i* h: L- M- t+ }# s
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
      f0 g+ f! H- y8 `3 C+ i2 s
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    ; m/ Y, }4 c1 ^5 q1 h- o+ Z8 [
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    2 E6 W2 Z) |3 Q6 F
  145.         }
    % ?7 |! s# o- [+ h5 f
  146.         else {
    $ n  H+ }+ N( {4 g& W8 S9 x
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");
    4 @0 R- e6 E; u2 D
  148.         }. o8 f* G+ i1 x& T/ n
  149.     }
    3 V0 A. g- Q# J& T" r7 z- h
  150. }( V- i- y+ k/ \; x
  151. public class Options7 t+ `/ V' E9 ]) u
  152. {0 @0 H. Q, ]0 E" n* L; d: P: `# P# ^
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    - R( j6 D5 E) R/ X/ S- ^7 I' M
  154.     public string Command { get; set; }
    3 ^+ e* b5 V# S7 A: @9 j

  155. 5 b7 G3 t& w1 c
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    7 Z7 {9 M& c# t: z) J" @$ S3 r# [
  157.     public string FileName { get; set; }
    # T2 U# n3 }' \: y
  158. % B% c: I8 Y$ n; r. h0 i: r: s
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]2 Q) a3 ?  y$ U' H6 O( P! i
  160.     public string Language { get; set; }' _( d3 H# b$ R" H$ t+ \. p& g

  161.   Y7 F7 x$ `# }6 }" E/ `
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]3 }7 V" E: ^9 q0 T7 ~$ W" A9 I
  163.     public string ModelName { get; set; }
    9 {+ n4 q) ]$ \: U
  164. 5 m, O% p, W+ ~0 q  x  L2 P
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]$ w' i& @' l% u! w, P4 E
  166.     public GgmlType ModelType { get; set; }
    ! e0 O. g+ i4 g
  167. }
    & d3 j# v, C& e
复制代码
) f* h) @8 b5 Y5 b, ^- c7 p6 O  r

. D+ q  u: c5 E6 a) n; t- W
( z9 C. T0 T  i5 Q# A+ g
! a" I' F3 U1 J" R0 |+ B
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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