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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑 8 G! ]1 t# }5 t* u' x6 W- m
5 j+ Z- ^' f+ `! _  ]$ z
本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,
. Z5 m1 ?5 U2 h9 c 使用时需要輸入语言,源文件路径和目标文件路径
6 @# `+ N& u9 }最后是输出srt文件
! C- ^  b$ O* W0 e# X4 z- f+ a. Z! i, v( ^' G8 |/ f! [" |
代码如下
) v& s5 V4 W3 a! E8 l+ ]- U以下这句用多线程可以增速,否则很慢
) _, z! C3 i( q% I/ Y- z# S以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。
1 O9 J) `/ W- h6 V# B% _& J' g# [* B3 z

4 r; e& F( J0 m2 }7 e6 i; _
  1. var builder = factory.CreateBuilder()
    3 Q2 V+ ?' N1 T
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码

- e/ c# ?3 r1 y% q8 j4 p) U$ R
9 H1 }; N6 E$ q  ]" e
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT7 f# @6 s4 k$ y  q) C+ a3 R, m2 _0 ]

  2. " e6 b4 k1 @! C
  3. using System;
    5 d+ E0 u$ I1 ?$ `2 d
  4. using System.Diagnostics;
    1 h7 b3 V8 h/ o2 Q7 Y0 W% _
  5. using System.IO;1 f# Y# T, \) B& `' Z
  6. using System.Threading;
    ) q7 ?$ k8 v$ ^1 w8 x  n* h0 r  v
  7. using System.Threading.Tasks;% d- V& z2 c- W' T* p
  8. using CommandLine;
    + T2 \+ d, b) A; \: Z# Y
  9. using Whisper.net;  e& ]& P% b8 A; u' Y) _
  10. using Whisper.net.Ggml;
    3 ^/ B+ g: s; j+ q
  11. using Whisper.net.Wave;
    ; X1 A' N& z5 y0 f
  12. ' u; y9 W5 a! S" B; M( o
  13. await Parser.Default.ParseArguments<Options>(args)
    9 N- N" x' I- O8 p% ]- b
  14.     .WithParsedAsync(Demo);; Q. C7 ?, z0 u
  15. , t# v! r+ {( J
  16. async Task Demo(Options opt)
    + s1 q1 u6 {+ {) B! M

  17. ' C. m- H# K1 {7 `% p- j2 `4 {; N
  18. {$ Z; f  u6 x) H, K# u; N2 h
  19.     if (!File.Exists(opt.ModelName))
    # Y* V5 N! H; @8 T+ B, F% j
  20.     {
    . k  l7 z6 C2 ^1 v- _) ]" V
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");/ B# d8 g) ]$ M8 s
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);. H0 K+ H* i  H( E; w- m
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);
    ; Z8 F) b- q) ^; e
  24.         await modelStream.CopyToAsync(fileWriter);5 p1 s6 |. M: n$ g& K% h; m" [
  25.     }
    7 z+ s% X* A; n+ e- u5 H
  26. 2 c) A1 ]; |+ g1 z! H& K+ V% i8 ?- t* T
  27.     switch (opt.Command)4 q  S9 n  F  r, z3 ?6 ^! ~
  28.     {
    ; p6 }, ?* q( c1 R. z
  29.         case "lang-detect":
    3 V: g/ Q! g" U. A8 B
  30.             LanguageIdentification(opt);
    : v1 a$ D8 q2 H. z; r/ [( J2 G
  31.             break;. M* n& k/ s+ ^" {1 l
  32.         case "transcribe":
    ( S' _: }( Y$ U3 D" ]: y$ g7 s- e
  33.         case "translate":
    6 J9 W& s; P/ S1 o: `
  34.             await FullDetection(opt);
    1 [- U6 V( l: J$ b$ E! O
  35.             break;* ?# Y. v, b3 x: }& s1 {' C
  36.         default:/ l* w7 @& J, z& e' D- D3 C
  37.             Console.WriteLine("Unknown command");" T* b1 w" V! q5 i
  38.             break;$ a+ V8 m7 ^* X9 d1 O  v; T9 X7 c7 {
  39.     }
    # H- n+ P5 y3 ~' S8 C# }
  40. }5 o7 W$ o/ s/ v/ ]
  41. 2 \# O0 t5 a- u# G! d  R( }
  42. void LanguageIdentification(Options opt)
    7 n1 u/ T- K) K! |8 G6 L" a+ r
  43. {
    . \) ]0 q9 Q1 W" E; O/ W
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);) t, [* q% R2 _; @; i; K! e( U: A

  45. ' ^! t# X; N8 g. F4 A( p
  46.     // Same factory can be used by multiple task to create processors.
    0 O/ ~/ ?; D3 r7 x
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);9 G2 X5 M. V! _' t1 R; _3 w1 e

  48. 7 ^! }7 f) \0 G9 @0 t3 _
  49. /*    var builder = factory.CreateBuilder(). w7 t5 `$ y& J2 h6 E
  50.        .WithLanguage(opt.Language);*/
    8 J; `% y: L( S2 o& ?" L  ^2 g+ B% a! o
  51.     var builder = factory.CreateBuilder()
    # E, s3 @$ _- O% Q/ j
  52.    .WithLanguage("english");; O7 ~- z) p- ]9 R( B1 _$ ^6 Y
  53.     using var processor = builder.Build();% ]% M7 m7 T7 `: a& U% l( B
  54. " V1 {  v. X# ]2 M7 X9 ]# {/ W
  55.     using var fileStream = File.OpenRead(opt.FileName);
    1 J" y3 E" C" R

  56. 7 j5 M: J- u1 z0 J
  57.     var wave = new WaveParser(fileStream);8 K+ P' D" T5 _8 Y: a) u
  58. + K0 i4 z& \4 K  \
  59.     var samples = wave.GetAvgSamples();9 M0 }3 l& w% W9 W

  60. : W$ M( P6 @, t% V: G3 Y
  61.     var language = processor.DetectLanguage(samples, speedUp: true);3 U  J- }6 f1 p5 G  Z2 }2 M1 W1 \
  62.     Console.WriteLine("Language is " + language);
    ) _- x, }; U$ U2 ]; p/ e
  63. }
    ; A8 |5 Y; |4 ]: I1 U
  64. , e4 Q* B* n, F6 z
  65. async Task FullDetection(Options opt)
    , d. {3 J  l" ^* Z5 y
  66. {. I$ |  l% W9 {+ a0 S6 C
  67.     // Same factory can be used by multiple task to create processors.
    ) G. }4 T! C% y- I( m
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);0 B5 `; w: p2 w9 t. T0 m5 L

  69. 9 [/ \8 _" \6 }( ~
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);
    . d$ [  T- a2 p# U; q
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");$ l& D$ N- l* V# K
  72.     string languageOption = Console.ReadLine();
    + L, P- ]' {6 Q5 ~) ]
  73.     var builder = factory.CreateBuilder()
    ' ?$ ?- S9 ?8 O0 k) _
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);1 c1 p- Y( Y, Q/ |" J  y
  75. : W  Q& f/ W/ f9 R
  76.     if (opt.Command == "translate")1 c4 r! S& `$ |% p3 Z6 \
  77.     {" ], L! Y- L& `! D& R- [
  78.         builder.WithTranslate();
    & x& \1 F  }0 x
  79.     }
    # D. _6 n$ J3 p2 v# R4 v6 M
  80. ( _; v7 `5 u- S. {
  81.     WhisperProcessor processor = builder.Build();
    6 o5 ^$ D9 K* Z' y& X3 s  U& A& ]
  82.     : o0 a) L7 ]6 w5 I
  83.     Console.WriteLine("请输入wave源文件目录:");4 b% b: s' ~. F; P" F% J
  84.     string sourceDirectory = Console.ReadLine();# f- {$ E, J: `0 f' r, N

  85. , B; d0 ], m. r- P
  86.     Console.WriteLine("请输入目标文件目录:");& `4 E$ p3 L: ^
  87.     string targetDirectory = Console.ReadLine();
    ) X! J+ u4 Q" M9 H

  88. - b# o0 ~7 H5 q3 s6 Z
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory)); V! E$ _' g* H: K1 b3 H- ]
  90.     {! a  P5 ]# ^  W' g+ n6 U
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");
    $ h  `+ R. z# ~. V3 a
  92.         return;
    - A: \# l) c& n1 y6 W0 G& C% p" F
  93.     }
    # j$ W: F, \0 I$ C% F8 C; g

  94. $ g$ x4 F- `+ s( T+ p: {
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);+ t+ F% ]# w" n6 t6 \5 P
  96. * @& ?: J, a5 `+ w: v9 C! O+ h
  97.     Console.WriteLine("处理完成!");
    / _# x( c6 n$ I/ n9 c* J

  98. . @9 w; C  L$ ^  F3 F9 L$ A
  99. }
    6 Z( d6 _& y# J2 P; y
  100. static async Task ProcessFilesAsync(WhisperProcessor processor, 8 |1 s1 `% m* }, d; n
  101.     string sourceDirectory, string targetDirectory)
    : O6 U/ k" ]. t- Y8 G& i) `0 ?
  102. {+ ?+ |( t- p9 Q5 k; K
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);
    . m3 @8 N* \0 e. h) p) i5 I1 b* l! L
  104. 0 f. l1 D) c0 C/ C5 M
  105.     foreach (var sourceFilePath in files)
    8 B4 k( t3 l+ G$ m0 h7 u8 x
  106.     {, \+ i. F0 }- m0 _9 s6 s2 D# n+ x
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    8 c( y8 @, J0 d& _: [/ V4 Q* d$ e
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);) S7 Z( l8 s0 @" K- i
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");. H+ r8 Z" Q" _) c2 W
  110. 5 J5 ]% v( v9 a+ ~6 Y  [4 O
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));
    7 U3 M2 Q$ p+ V4 L& U! x- i
  112. ' v! u, u  F/ p7 g: G* c) e
  113. ; ?5 R9 F! S6 b# M5 Z/ [8 l6 X
  114.         if (!File.Exists(destinationFilePath))
    ) b- R" \+ P3 A" o9 o1 `+ o
  115.         {
    1 L- r  {6 T# V' r! T& A
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");# Q  c6 e$ w; v& o9 l; \$ }9 u( `

  117. 4 s! o, T6 q2 L
  118.             using var fileStream = File.OpenRead(sourceFilePath);
      e6 L6 q) o- t; L5 X
  119.             var segmentIndex = 1;
    ! F$ y& ]0 N2 i! f
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter  q! v- U/ \% C) E0 s
  121.             var startTime = DateTime.Now; // 记录开始时间: x) [0 ?4 }' d9 w0 W! N( }9 A  o# p
  122. 4 E4 o0 `+ q) R* [3 N% f# C
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    & x0 E" n9 Y) C9 M, U$ l
  124.             {$ f" [0 \5 p% i9 c! r2 J1 \* w
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");! l, t( m$ Y0 l* _' R
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    . F( C% d" y, d" y; N& L9 f' B
  127.                 Console.WriteLine(segment.Text);
    # x, S6 O) S- e# M
  128.                 Console.WriteLine();
    " m+ ~4 x) q  P
  129. $ L$ j% v1 S$ Y
  130.                 // 将srt内容写入文件
    ) [# `& `  d+ I: d) M. ]
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    1 a4 W. q/ G" h/ U5 X2 O) F
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    ( w8 i6 ?; A3 F" c) u2 B2 M
  133.                 await writer.WriteLineAsync(segment.Text);
    $ d  O3 ]6 e3 H9 y* o& S5 o* G1 y
  134.                 await writer.WriteLineAsync();
    9 s& c$ z" ]% {! h. z
  135. # e" D$ q, T7 A& f# i
  136.                 writer.Flush(); // 立即保存srt文件
    4 i" X0 D" f- s: m! x
  137. 5 H3 `0 Y; h$ D: n  ^' A
  138.                 segmentIndex++;
    2 J9 ^$ Q1 \! a7 f4 a! k3 c
  139.             }
    # s" ~6 m7 s6 Z
  140. 4 ~1 G  q" i- y" a! l0 `% e
  141.             var endTime = DateTime.Now; // 记录结束时间+ y+ ?) ?; G( ?- q( b4 K+ Z/ W
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;% c( p- p; P; e( S$ M( l% B. u
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    6 G9 r; H" m+ T& T7 z- D
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");" l2 ~2 }! M7 j' \
  145.         }/ [- U1 u' J) ~! O
  146.         else {+ H: D5 B2 u2 i' ]  H7 V! Q
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");* S# n3 V" C" o7 V' \" B
  148.         }0 M, {9 w. m  H  W
  149.     }7 O- ~  e: u. ?: b
  150. }. N$ C/ A! [+ j3 d4 t
  151. public class Options% I6 D, U+ n$ S  Y
  152. {# [8 n) M0 R9 P1 z: i- u
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]) H* T; m/ d. ?1 w/ D+ u
  154.     public string Command { get; set; }
    & c2 V5 ~4 h$ y- I& R9 w# j" a) N

  155. 4 l5 h& e7 k# X( ?4 p5 g. q
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    4 o, |! o5 {) J( A
  157.     public string FileName { get; set; }
    % W( |. r: K: I  U" w0 [; S

  158. 8 V- T/ o4 P$ x( Q
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]( C0 E! S9 q4 ]
  160.     public string Language { get; set; }3 I, V! g# M7 i! \5 b; x
  161. 6 z: L5 D& A) U: E; {$ J
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]
    $ a5 g" x$ f$ ~: R; ~: s
  163.     public string ModelName { get; set; }
    1 d# H! }# J/ Q+ |. W( Q; D$ s

  164. 0 V7 y& I3 l; b; a! ?% Y' h
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]5 N2 z! t2 `8 `" O: P1 \: A+ |
  166.     public GgmlType ModelType { get; set; }
    5 m! o0 |0 w" E# F7 X
  167. }
    3 d6 G: s$ e  X: z( v3 p
复制代码
- p; q6 c: P) f5 n3 h# |" H
  I# t3 p4 R% Q. g
% C' E% w* d' t" r. o+ N) r- H
, A; @( \7 s. v9 b/ ^% M3 B) h$ A( O
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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