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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑
4 h% o* a6 F7 ]  ~* l% v1 ]3 \( s9 S* ?: U
本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,
. H& k1 T5 y% \/ ^, F 使用时需要輸入语言,源文件路径和目标文件路径
8 n) V" w% e3 l3 C; ]最后是输出srt文件
5 {' I9 A  ?/ f+ r4 H+ `% j7 L; x
) ~& e9 d' Q! K: z/ f4 I代码如下
" p% V1 i  c1 d( R2 x以下这句用多线程可以增速,否则很慢1 t; `3 v9 F4 |" Y9 V
以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。% J; o8 B0 e: I
( }" e7 K* x. a2 t9 @
2 w2 ?4 w# {9 W2 [) c
  1. var builder = factory.CreateBuilder()
    2 g5 W7 p, k+ B. j" E# G
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码
) t3 ]3 h6 \8 }1 m  h
3 J; x+ Q! o, n4 z/ Y! k
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT7 x! s, h% B6 @3 a

  2. 3 j0 Y  K% i, i4 w0 O
  3. using System;
    . X) j" h; c0 \$ P$ P6 {7 Q! Y! y# E
  4. using System.Diagnostics;
    ) b7 ]9 P7 N' B; L- H7 g+ D
  5. using System.IO;
    ( j8 v: S. @! m9 G6 {0 w
  6. using System.Threading;5 Z4 g$ B- z/ _8 [9 w( v
  7. using System.Threading.Tasks;  u) x2 X; o& P  B0 E3 M
  8. using CommandLine;0 I% v" S! Z( I8 I. ]
  9. using Whisper.net;
    9 \: g. t9 D3 Z+ h
  10. using Whisper.net.Ggml;
    ! Q7 D; F+ V" g9 C# l# E
  11. using Whisper.net.Wave;
    $ r+ j) _2 n# a5 J
  12. , ^0 _/ ^  j4 ^7 U; C& i& j. ~
  13. await Parser.Default.ParseArguments<Options>(args)* \+ `' ~7 D  d
  14.     .WithParsedAsync(Demo);, w0 N2 _+ [5 o. e" P8 ^8 o, G
  15. ( F! R% {5 C: V2 T8 n
  16. async Task Demo(Options opt): f6 o: J7 A, |: c% Z% x
  17. 1 }# y/ I& n  W3 d% Q+ s
  18. {( y: V0 a' f0 q9 y) E0 D( _1 V
  19.     if (!File.Exists(opt.ModelName))
    : x2 b1 I! y1 Y" `+ G7 |" A
  20.     {3 m7 g8 K) h2 |5 W& r
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");
    & L6 Z% S) Y/ L# I* h
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);
    / O: E+ a! O5 G$ X. h2 ?( a4 A, E) o
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);' d6 U' b& h2 h: ^. I/ \2 w
  24.         await modelStream.CopyToAsync(fileWriter);
    3 C2 |3 Q, F% X1 L5 i
  25.     }7 V5 }* t) D/ b" l

  26. 6 x, t% d% \. o; W$ b8 q7 K- f$ b
  27.     switch (opt.Command)
    # l' \. U0 C' W0 `& E
  28.     {2 j) @7 A$ o; O& _. Z1 \. ~3 B. s+ S
  29.         case "lang-detect":. \0 D  a& k/ o# [" E
  30.             LanguageIdentification(opt);" l! e8 o7 A5 O
  31.             break;
    7 C0 \1 s  k9 A: V' @9 }# U
  32.         case "transcribe":5 w- w$ Q4 r. a
  33.         case "translate":
    # ~. e! D. c+ d7 ?
  34.             await FullDetection(opt);* `" U$ ?# z7 M# Z
  35.             break;
    % ?! Q) ~: N; U1 H% s
  36.         default:
    * |) T) Q( ^( f6 G1 L) B% T0 _
  37.             Console.WriteLine("Unknown command");# L6 \# N# ~8 E7 Q& g0 p
  38.             break;
    : F/ |7 {, J: k5 g7 {
  39.     }# V& y* g+ _3 o% c- O" h- `3 c9 h
  40. }
    5 b! F' t* O( v: [! R

  41. . ?. {/ `' k; G& R! f( W
  42. void LanguageIdentification(Options opt)  o( Y& K5 e( P* x  [' R  g
  43. {" S$ c" g( ^! l
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);
    0 @6 u! _7 ]- C' [

  45. 7 i0 c$ O! L! l9 A2 N
  46.     // Same factory can be used by multiple task to create processors.7 g8 F% c3 R- h
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);
    6 u8 D1 w7 p" l" ~5 c

  48. : V- [3 q% f2 V6 j4 W
  49. /*    var builder = factory.CreateBuilder(). ?  a: Z$ x8 L+ {
  50.        .WithLanguage(opt.Language);*/
    % c* a0 Z5 T  h5 G
  51.     var builder = factory.CreateBuilder()) H- w' U& K: T, A8 L9 v
  52.    .WithLanguage("english");4 Z, ]: m# [" R5 s' Y
  53.     using var processor = builder.Build();
    0 t" {$ {* N0 c( |* \. W

  54. + m" O! s& e5 D8 f
  55.     using var fileStream = File.OpenRead(opt.FileName);* L# E3 ^. L, }- ?& j- F' h/ V
  56. & @, m% T  o5 X+ p+ G( N, t
  57.     var wave = new WaveParser(fileStream);; v. z/ Z/ G# c& z7 ~/ w: `
  58. 1 P4 X  w9 |9 \* ^7 |. a
  59.     var samples = wave.GetAvgSamples();- P! R4 z1 m* g6 M1 ?' u

  60. 3 M# Q+ }/ A9 y! H5 t- L9 Z0 F
  61.     var language = processor.DetectLanguage(samples, speedUp: true);! l4 c: n7 P' `/ n* b" m. b
  62.     Console.WriteLine("Language is " + language);
    / [0 C4 R" A# i" v6 B
  63. }
    , z+ n5 C+ J: [* `5 a  |! d  w
  64. $ K7 t4 d9 a, Z
  65. async Task FullDetection(Options opt): P$ E0 G; y8 N6 v  z
  66. {
    7 ]5 a" d  F: m! h
  67.     // Same factory can be used by multiple task to create processors.
    ) t8 s1 E& J' x1 v6 n  s# {
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);
    & {0 C. b5 j  ?' {# f- U

  69. . B' j2 Q/ p) G. ]" a
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);
    9 I3 p# {" k5 ]. ^5 L
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");7 b% h( r; Q" X2 X$ I" l
  72.     string languageOption = Console.ReadLine();& E" h5 c0 D+ p  W8 ]/ O4 j
  73.     var builder = factory.CreateBuilder()! }: B" _: n& H' G& f3 [6 O* d% g+ l% G
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
    ( c; x* t' F# P9 r& m; y& [+ ]

  75. 9 @6 }' t% R) R3 L7 F
  76.     if (opt.Command == "translate")
    & [5 I% F2 u3 P% t
  77.     {6 o: {! V) d2 r) x
  78.         builder.WithTranslate();
    3 ^; q7 H: _# l) u
  79.     }2 x& g$ X  H/ M& L, t8 @1 z! ?
  80. 1 H+ S- K5 {0 D/ z9 H. B3 U. a; r
  81.     WhisperProcessor processor = builder.Build();+ ?5 Z9 {* {3 n6 R
  82.    
    . T# d( V. n2 b
  83.     Console.WriteLine("请输入wave源文件目录:");' p/ b+ b4 n) S1 M) f( L& r$ F
  84.     string sourceDirectory = Console.ReadLine();
    7 C3 @4 z! x( h$ t
  85. ) z% _) a& q/ \0 T5 h! s% a8 {
  86.     Console.WriteLine("请输入目标文件目录:");
    $ y7 P; F- d+ K
  87.     string targetDirectory = Console.ReadLine();: Z) n, w  M' w& c! @. C& G& Z

  88. - u3 K, B, i* T4 n! s
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))) f+ C1 V9 }' o- R
  90.     {
      X4 I2 _) Q( F9 w$ m8 u7 [2 _( q
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    - ]! \! R9 [3 L$ N( O3 q7 h. [
  92.         return;
    4 v# }0 v2 i7 B* u9 r8 r* J
  93.     }  b% z& ~8 p6 i# K9 u+ w5 l

  94. # o- b. X) O% O1 g: a. O; G
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);
    4 r/ Z0 J" i0 A# J5 ^; d
  96. 4 [6 U% z8 T1 |) j# c/ r4 W/ E4 J
  97.     Console.WriteLine("处理完成!");) r  Q+ o# R- I, E
  98. / d1 p) G9 R4 z; j2 w) F& E$ Q/ }
  99. }
    ' L! B2 m5 K6 G- l' f  ]
  100. static async Task ProcessFilesAsync(WhisperProcessor processor,
    3 \! S0 k0 I# C9 R6 ~" E, e3 z
  101.     string sourceDirectory, string targetDirectory). ^! i. V) j5 |% g
  102. {
    ( W* P2 d1 L8 i) }# T# q% p
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);
    & o& N" {1 ^1 S6 Y

  104. 0 h6 ]  p$ K0 j1 F" E
  105.     foreach (var sourceFilePath in files)
    & V* U0 }8 H2 g
  106.     {/ z' k8 }' Q2 {8 m1 J0 i7 g, O
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    " T1 D' z5 Q# o
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);
    & N& R  a; ?% j* Q2 ~( q$ Q
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");' g2 ]/ {5 S! ]8 f& E

  110. * H) o: o* Q* y3 [; l' Y) u
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));
    $ j$ o) |% A9 n

  112. : Q: j( d0 E' Q; }6 W

  113. + y3 Z  y! E& s. N
  114.         if (!File.Exists(destinationFilePath))8 P6 s9 v# p3 q: u* d
  115.         {
    ' c( c% x3 D: ~1 C) j
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");
    / E4 n0 `1 D1 ?) r
  117. # \) _& v5 j4 n: X% [5 B3 ?7 z
  118.             using var fileStream = File.OpenRead(sourceFilePath);
    : z/ E2 A1 x0 L7 u0 y# K
  119.             var segmentIndex = 1;0 [5 G6 g) O0 K2 D8 j; ?
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter4 e' `6 F; b0 E. b
  121.             var startTime = DateTime.Now; // 记录开始时间
    4 v6 E! @7 M- k- u

  122. , W3 {, T$ |4 U$ H9 r! g  s8 ]
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    + \; {& {' c4 c& K' \. d/ u
  124.             {7 A" h% M0 W- i' ?; z; Q# W+ [
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    8 _# h8 s5 Q; d7 x3 X7 R1 V
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    - c, U8 s. H" a+ B
  127.                 Console.WriteLine(segment.Text);! F  m/ A7 a  v4 ~$ D/ R
  128.                 Console.WriteLine();
    $ h  ^. R6 @3 [' `' H

  129. % m1 w0 U% t" X8 Y- ?
  130.                 // 将srt内容写入文件
    % s8 n5 i+ i3 M4 F, |. A
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");  W% z) n; V, z/ I# X  U! I+ _3 @
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");9 M* q2 F/ F/ X% g( N+ Z8 L
  133.                 await writer.WriteLineAsync(segment.Text);6 D' k* g! ^" _, P
  134.                 await writer.WriteLineAsync();
    $ K& M8 {9 F* c4 s$ j
  135. 3 _" f# @5 V7 }, N
  136.                 writer.Flush(); // 立即保存srt文件8 C3 j* {3 n) t  Z

  137. & ~, C9 I! b  T3 J7 x& g
  138.                 segmentIndex++;
    . ~, A- T3 x9 }! T- k
  139.             }
    * n6 X1 v$ |; I. I

  140. 2 L# I2 W" A3 x/ A% Y& ?4 D
  141.             var endTime = DateTime.Now; // 记录结束时间; {  z2 W0 e6 |( g
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
    . k, v. k: E: _! n# Q% C
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    3 p# a5 d; ~* w0 a
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    # u, Z5 N# B$ ^4 r5 a) |- L
  145.         }/ t  |% J) N8 k4 e3 u; y
  146.         else {
    ) A3 V; l3 [- S( ~( q  X
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");
    8 C9 P# L# ]  e3 u6 n
  148.         }1 ~: q* \' N9 n; R- k5 G
  149.     }
    1 a  T6 Z/ r7 ~5 N  @
  150. }
    - k& M* l( e, z' n# V' D2 u& b- h
  151. public class Options) |7 u  V8 d4 U) q
  152. {4 Z# v' [$ E( K1 ~( F
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    ( y$ [& _6 }9 l2 u) L, I9 n) C
  154.     public string Command { get; set; }
    6 P# i% w5 a8 E/ ~. M* O
  155. 9 B1 j: `( v$ F6 ?* V6 V9 I
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    " L* f$ O9 s6 D, d" i
  157.     public string FileName { get; set; }' p& Z+ v" F& k
  158. ) x7 C! @/ y. e5 C, j* r  M& @0 o
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]3 q% S% ^: l, n4 @
  160.     public string Language { get; set; }+ ?' b; p( `) W$ [1 d

  161. 6 n: v/ n- \" V- L9 c4 ~6 f4 \
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]& Y1 ]1 h4 d- h6 P, h4 t1 W6 D
  163.     public string ModelName { get; set; }9 ~9 {% o5 Z2 A% G1 o1 \& ?$ m
  164. " ~3 A6 W" M0 f
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]9 }, s. }. p, z3 _1 }. Q
  166.     public GgmlType ModelType { get; set; }) b! {" Q* P1 F5 c5 s& x- K7 h
  167. }& p0 i! \; Y, Y4 Z5 ?) Z8 h
复制代码
% g& h% G% A& U) N) m* k
0 p' M% J8 Y+ l% S1 J: ]" u

9 Z$ H# R( w4 _4 }/ H( [
) x# [- U# m- s0 t1 t- x
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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