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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑 / I( M# n8 T" R' {0 L( Z
8 L  f0 _4 x- Y! u
本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件,
1 n6 d& T# i0 X% R: S2 S+ `( q 使用时需要輸入语言,源文件路径和目标文件路径' S! x- Y' r( s$ w# {: C' X
最后是输出srt文件
6 R6 m5 g9 j! j0 b" a/ o. t8 q3 `9 `% @& {
代码如下# j& E! ^8 R$ p
以下这句用多线程可以增速,否则很慢9 B% C( B- x: h4 {5 b0 a- a; k
以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。
: w$ k. R) n+ `( J. c4 C. J  O- v/ \/ c) z  w
6 j2 |( W/ `% j6 s9 y1 n
  1. var builder = factory.CreateBuilder()! s; L4 S, D- v  Y; O+ g1 d$ H# Q
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码

, S( n- c& [* V9 z
% X$ b1 j6 S# p) H2 A& @) K
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT- V3 f" S9 ?9 ~( h7 G0 B" J
  2.   o$ Y. O9 u+ [) M! |+ N
  3. using System;
    $ E; n9 p- f4 y) x  h& j
  4. using System.Diagnostics;( z/ k$ B' W) K" E0 ^) Y- e5 M, [, R
  5. using System.IO;
    # @& E% t8 [! A' E' x$ p! T
  6. using System.Threading;
    . Q" \5 X! k1 Z3 z
  7. using System.Threading.Tasks;% q2 U2 r# P: r& c) i
  8. using CommandLine;7 I* y* {% J0 S; ~
  9. using Whisper.net;
    6 j8 o* \$ J3 r% ]) K
  10. using Whisper.net.Ggml;# I5 @$ R; T3 h. Q7 G) i. ?
  11. using Whisper.net.Wave;
    6 e1 _/ ]0 x8 ^' c% V8 X" v1 n
  12. 2 I2 Y9 X8 X2 w  d1 c  o
  13. await Parser.Default.ParseArguments<Options>(args)- M- c# I9 a) x! e, Y+ {6 d! e
  14.     .WithParsedAsync(Demo);& M4 E! J' W' A$ E! `/ |. S; H. d

  15. / I( w3 m$ r' N7 Q" I5 m
  16. async Task Demo(Options opt)
    % n4 k+ r/ I/ M& R$ S" N: {* |

  17. ( ?& D3 b* C, Y3 k# O
  18. {
      x3 ~" J. c* v! k$ O8 ^
  19.     if (!File.Exists(opt.ModelName))
    # {$ f2 t: N/ V" ~& F' Y
  20.     {
    6 r/ J  D( o/ R
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");" W4 |" o3 {" F: z+ T1 \* X, r) t
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);- }% U) h! t' I+ u: ?
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);
    ( E3 v1 C4 _( G( z# Z
  24.         await modelStream.CopyToAsync(fileWriter);
    8 W1 S  X6 Y' m* q& Q( X
  25.     }
    / o9 R# o& `8 \" x# P' e
  26. # ~; N+ C+ k. B! k! H1 @
  27.     switch (opt.Command)$ ?. d( t. V) y6 G7 Q( f7 i) }
  28.     {
    2 I! Y/ ~  k: m
  29.         case "lang-detect":
    3 A, f* d: i0 U3 k2 E8 s8 D3 w
  30.             LanguageIdentification(opt);
    6 u0 V1 n8 Z) t9 U  S
  31.             break;1 h+ T$ P, @+ A+ k) e
  32.         case "transcribe":
    & V* q7 [& R' F
  33.         case "translate":
      K$ Q" R  m! y
  34.             await FullDetection(opt);
    , `9 q- p3 y! X& E1 o
  35.             break;
    6 v1 s# C+ T. ^2 ^- p5 R' X
  36.         default:* {& [% m: \" z' z+ _
  37.             Console.WriteLine("Unknown command");
    / X3 w% y6 j+ I4 O2 p' ?0 k
  38.             break;* u& i  ]5 m( {; n# O7 F( k) L' X
  39.     }
    & j5 M0 t6 H! l4 w
  40. }
    " C0 G7 K6 u* b  c

  41. 9 @8 t; C, [2 J
  42. void LanguageIdentification(Options opt)
    6 N: E, r+ s% S# M) V
  43. {5 a9 m4 z3 [  m# f  j( V+ U& V- a
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);- [. i5 o; g8 W# ~. \7 y

  45. 0 B, u; o* h8 t- D' d8 l
  46.     // Same factory can be used by multiple task to create processors.
    " m* O* U" f! F4 W0 L
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);" M0 v  |- Z2 x; D( s
  48. 7 n6 {0 n) ^8 k- w$ A, T- y. U8 q
  49. /*    var builder = factory.CreateBuilder()
    ; V2 @, C5 F; t
  50.        .WithLanguage(opt.Language);*/8 k0 |. K. {( I  W5 Q
  51.     var builder = factory.CreateBuilder()# M+ j$ l: ^8 m, |1 Q9 Z/ Y* g
  52.    .WithLanguage("english");8 z- }, b& z& E' O. w5 Y
  53.     using var processor = builder.Build();
    " Q& v2 `+ v- r

  54. ' y, y+ Q+ T& i/ d1 N  ^
  55.     using var fileStream = File.OpenRead(opt.FileName);
    4 P3 b# Q9 b# V( ^
  56. ' ?. Z, b, S" j0 ~: p
  57.     var wave = new WaveParser(fileStream);
      X) b9 B' F2 ?6 U1 f  @$ z
  58. ! b6 `+ N: m/ X0 S% h5 |9 r
  59.     var samples = wave.GetAvgSamples();
    " F' x: K: U# K8 P! \6 k
  60. 5 s4 Y1 y( m" }) N% P2 ^. h! t
  61.     var language = processor.DetectLanguage(samples, speedUp: true);9 h+ t4 x* z- f' ]5 ]: k. E6 T& q. Q
  62.     Console.WriteLine("Language is " + language);
    ; _6 \; Z- `8 }, |& u$ A
  63. }
    ; j" W6 X/ q, Q
  64. ' B5 ?  ~% |& p: O! }- `, y8 B  S
  65. async Task FullDetection(Options opt)
    5 P% G0 S1 S& j8 {& c( r5 X
  66. {
    ; w, ?. O+ Q) ~
  67.     // Same factory can be used by multiple task to create processors.9 u' w* e: x$ H# [/ D
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);" F, j3 z4 }# b; ?* h

  69. * z( F8 l, e$ ?; w
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);
    ) R8 y) m) ^) T. L6 [+ d# w
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");
    : k: @, M% l' y. m
  72.     string languageOption = Console.ReadLine();' Z: W/ r: O; Y% H* `4 \
  73.     var builder = factory.CreateBuilder()1 A" D: z0 A/ l. k. j
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
    / _$ m7 r. X# j) a! v1 Q- B
  75.   W! G3 K7 x- M7 t
  76.     if (opt.Command == "translate")- j$ W( {1 h  M4 a
  77.     {
    ! `- i$ d/ [8 K$ Q
  78.         builder.WithTranslate();: s! T. Z2 }+ w, n9 ~% w$ @) f
  79.     }
    7 `8 c( C, \: k  m

  80. 5 o/ m4 B' [+ V; l8 h; ~
  81.     WhisperProcessor processor = builder.Build();  P; q) W8 [8 Z* h* r
  82.     - D$ V2 R/ q4 K; ~6 b2 N4 [
  83.     Console.WriteLine("请输入wave源文件目录:");- T( _" y* m# C: O; J& d
  84.     string sourceDirectory = Console.ReadLine();% x2 n+ ~9 O  Z' c; `) ]
  85. : O- l& s" ?$ y
  86.     Console.WriteLine("请输入目标文件目录:");* L& e5 l* ]9 n' e3 y
  87.     string targetDirectory = Console.ReadLine();
    9 A8 {# a: q0 }" t+ m9 J

  88.   j4 s4 s/ |1 ?; T6 X
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    / P+ R! r: n* N! G/ i
  90.     {: L) v; x2 D, U% t; y. c
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");8 {: s! W, o  N6 n0 Y! [
  92.         return;
    " g2 j6 F6 U6 u5 e9 z: @& z5 M' [
  93.     }+ ?8 j7 v7 J- Y+ K8 H& G; ^+ J3 I
  94. 3 w* {, {: g4 B6 I1 ]1 p! C( M
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);4 v2 o' g, |; Z  r) F: `

  96. ! m- L- z. {# ?8 u/ d, d" }
  97.     Console.WriteLine("处理完成!");
    % f/ R. H# k( T! P7 p2 g3 k
  98.   ~1 L' |  y* @) ~: l2 n2 W' ^
  99. }
    5 {  B3 L& A+ k/ u3 R
  100. static async Task ProcessFilesAsync(WhisperProcessor processor,
      a7 t# t* P' u: U5 U' r
  101.     string sourceDirectory, string targetDirectory)( Q; l* q3 W! a# W& F$ Z
  102. {6 |$ n: Z5 E0 M2 X. P
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);
    : g- |& g8 u5 Z# K3 u9 [3 S

  104. 1 z5 i% j! I0 h5 C4 T, s
  105.     foreach (var sourceFilePath in files)( w& u+ _3 R' p; _! E  T. Y6 R6 t
  106.     {, `# x4 b9 X: [
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    2 ?! j1 Y3 L: `0 T  z& ~: i
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);! @5 A  X, O2 C0 f
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");
    ; h' k4 w6 O. T

  110. $ J" `% h5 W0 i; ]6 Z" L7 \7 y
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));& R3 [$ H. D% O* R: M% m+ \3 h
  112. 0 A6 B$ n. U3 h) ~' [

  113. ; J! b% V5 K% \3 O
  114.         if (!File.Exists(destinationFilePath))' p" j1 N/ c( E" c7 \
  115.         {
    ! E& a$ i  c+ a2 Z" U/ i
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");
    & A" o4 i6 V% Z  ?

  117. 2 S) K( P. D1 U/ b- }) y
  118.             using var fileStream = File.OpenRead(sourceFilePath);
    6 a9 J, A# ^7 c, w; L* O5 l7 W
  119.             var segmentIndex = 1;% E0 v! q  u& r* @
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter
    + N1 k( Y- g2 L/ ^; E: B
  121.             var startTime = DateTime.Now; // 记录开始时间
    7 I8 j6 m% o5 N# m) }6 }

  122. * s; s$ X; f) B
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    / o1 A3 k/ d( C& {
  124.             {
    " e; S5 {, K2 Z1 R) U
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    $ o7 i8 D# w2 ?( j8 P* d8 r# u4 p
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");8 |) W" V( ]* v# J8 p& s
  127.                 Console.WriteLine(segment.Text);/ w6 `( T4 H& q, t/ y
  128.                 Console.WriteLine();; E. e' m4 P1 N, D9 z: a
  129. - T# X2 a8 c, A; X- Z! T
  130.                 // 将srt内容写入文件3 N# d7 }" _5 l3 _# }
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    4 t6 c1 Z6 v! g6 W' o* j( C
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");& a( k' u1 v. ]  l1 _
  133.                 await writer.WriteLineAsync(segment.Text);( @# x( k/ E. t( C  t) e. z
  134.                 await writer.WriteLineAsync();# C8 u' T0 ~+ |
  135. * r1 }2 ^; L# J" K- [, Q
  136.                 writer.Flush(); // 立即保存srt文件
    1 c4 B5 S7 o+ m/ W
  137. % |$ o( p# p; s' t
  138.                 segmentIndex++;
    ) K7 T8 D% t7 q4 X+ {  t3 R8 x4 F
  139.             }! t2 p9 G9 `3 }1 C% R  Z3 q

  140. * E" _% X% k" f$ _% P5 m
  141.             var endTime = DateTime.Now; // 记录结束时间, W9 @. g5 \! Y* r7 X1 ]
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
    / n: A/ }5 I) }1 _8 _. M
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    % Y$ C, W- t! o' X" K' V! G
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");# @7 e0 n* l* `5 `
  145.         }
    1 f. A1 t% T+ y
  146.         else {
    . f1 N6 v7 G" G# B/ q$ s7 o
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");' f2 H0 r5 n3 N! S8 p2 }& z) V) h
  148.         }  }7 g& O3 r' `! u
  149.     }) {  e2 x/ d' ~2 W! t& o7 \
  150. }
    ! v! y$ g' B, K" K
  151. public class Options; W6 Q5 _& V( t5 a% e
  152. {
    3 x; j- E' P& O% Z  w
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    6 Y1 O; U* p# N& I
  154.     public string Command { get; set; }
    7 q& o' U- Z3 G
  155. * |) r3 K1 @& U6 b) {
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]
    % X6 \- p% e! u6 u: {& d
  157.     public string FileName { get; set; }
    7 V. i' j- s7 w
  158. 8 ~1 m. y# B8 {2 t
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]6 H2 N  s, x( H* V& X" s
  160.     public string Language { get; set; }% R7 D- Y1 P( ]% `( K3 @

  161. 7 r' M2 N0 [& G: q2 r' ?5 Q
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]" ^7 ?5 i( i* H+ f6 N! i4 u
  163.     public string ModelName { get; set; }
    ; q. q, G0 }8 _6 E( }- o' Q" t
  164. # g& R7 g, S* @# e4 m" h/ o
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]8 a# q4 V! |$ C
  166.     public GgmlType ModelType { get; set; }+ y0 ]) `2 t- k/ k
  167. }
    ! d2 x8 o# w/ d$ V- R5 H6 v
复制代码

5 h* ?  k# Z& ~; u8 N$ T
2 H5 g7 ~* u/ q! ^+ Q/ S2 Z# ]+ q3 H! P4 E2 J
* G: s3 g2 d: M! L% J
分享到:  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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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