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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-4 12:57 编辑
8 `5 G( o8 S6 q; D* n) _( N, K# X1 J5 e0 S6 z9 A% ^
本程序是在Whisper.net.Demo基础上修改的,可以批量识别wav文件," A7 A' w* Q# u9 Z9 S" j* e
使用时需要輸入语言,源文件路径和目标文件路径
. K( P( F" P* Y最后是输出srt文件9 x( g) I' v5 l, p6 b
6 k: `$ ]& \7 A
代码如下- n3 v$ \& O1 q" W7 n8 Y. Q
以下这句用多线程可以增速,否则很慢, n4 r# t. n( O8 F
以下这份代码,还只能使用到CPU,速度依旧比较慢,使用CPU的方法另行研究。
& q* V' p; e7 p2 h( n
1 K) h( e1 I. m9 b0 i/ I! I4 P4 l0 S, Z8 p3 f( d
  1. var builder = factory.CreateBuilder()
    0 Z1 p4 m2 z* B: s2 Z
  2. .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);
复制代码
3 V9 D% j1 U' E

* K- o0 \9 P* E+ C' u: z
  1. // Licensed under the MIT license: https://opensource.org/licenses/MIT
    1 c1 x: {+ R+ M2 x% S( {/ t

  2. 5 u0 ^3 N, b8 C$ O* G1 Q
  3. using System;
    : M( Q: f- w9 K, I2 }
  4. using System.Diagnostics;
    ! f; ]! g- N7 c+ H
  5. using System.IO;
    / v7 j$ Y- e5 N
  6. using System.Threading;
    & L; U- D! ]3 A) A
  7. using System.Threading.Tasks;
    7 T, t6 j  g0 x6 M
  8. using CommandLine;
    8 [$ A3 z- c0 v5 R( B, {
  9. using Whisper.net;5 }; W) a% @& f; q) T+ O
  10. using Whisper.net.Ggml;( y. O6 X, F% _; x. @+ c
  11. using Whisper.net.Wave;
      d. o/ _( E# ?( k: {. r
  12. * `; ~/ A, O8 w( p$ I
  13. await Parser.Default.ParseArguments<Options>(args)( ?. e- v9 N6 a7 Z, F- N. W
  14.     .WithParsedAsync(Demo);
    % @1 A/ c! W+ d; P' V# n
  15. 1 w3 @6 b7 ^4 D" O3 o. X2 W+ G
  16. async Task Demo(Options opt)& Z, F2 F/ I4 W- v# ~# }$ |8 u

  17. 3 }/ B8 w) [: I; N) w' g1 b
  18. {8 Y! N& z# I/ N  ~! o) Z+ r
  19.     if (!File.Exists(opt.ModelName))
    ' i) ]! c# B# u% H
  20.     {
    + p7 W3 e% D* ]* b5 J. G9 N
  21.         Console.WriteLine([        DISCUZ_CODE_1        ]quot;Downloading Model {opt.ModelName}");
    ) i: ?7 T3 l( w7 J0 O* D
  22.         using var modelStream = await WhisperGgmlDownloader.GetGgmlModelAsync(opt.ModelType);
    ) \& j% r, R# D) o2 m4 s# j" [' ^
  23.         using var fileWriter = File.OpenWrite(opt.ModelName);
    ; U1 C5 {5 d; A; q) p2 U# a& z5 {
  24.         await modelStream.CopyToAsync(fileWriter);3 g* k3 N% g3 W
  25.     }8 I6 I1 }4 x3 `% v
  26. ! a( K+ C3 h. ]2 y& A: M& c" N3 u
  27.     switch (opt.Command)6 O! D  e" Z" F# V* w' c
  28.     {
    ' Y' f1 @, S; r, j) [/ t
  29.         case "lang-detect":
    " K( o1 n3 G: C& c, w0 M& X9 n
  30.             LanguageIdentification(opt);& y0 Y$ U/ i- i) u4 N" |
  31.             break;. O# H1 z: J# y9 i8 n9 Y
  32.         case "transcribe":/ B  Q" Q/ G/ t2 }# `" U
  33.         case "translate":
    : p) o& F0 F! C# C
  34.             await FullDetection(opt);
    4 j4 u) i5 |, V+ I
  35.             break;7 I- F+ T; Q* h3 W, X
  36.         default:/ e5 U! R" F; C  m3 \
  37.             Console.WriteLine("Unknown command");
    $ e- \' j: u$ E' Z$ s3 J0 i
  38.             break;
    0 ^- z% L5 K" y8 w4 L/ Q! M
  39.     }
    3 U! @* c5 j* g8 x
  40. }
    ( Z; z3 b) d& o( u

  41. & L: {( j1 K. L1 q+ o; l8 a9 V' c
  42. void LanguageIdentification(Options opt)
    3 G0 L8 `; v# _. n( L' Z
  43. {
    / K. h7 }  m# [7 X1 h2 A) f
  44.     var bufferedModel = File.ReadAllBytes(opt.ModelName);4 [$ a: _' E$ w. m

  45. . O' r6 |0 h' }1 i% M" K" C$ T8 H1 F
  46.     // Same factory can be used by multiple task to create processors.# G* [: g) [) A) r
  47.     using var factory = WhisperFactory.FromBuffer(bufferedModel);
    & Y% O* o0 H# }9 D, N

  48. ' |& p# l+ B- y
  49. /*    var builder = factory.CreateBuilder(): s7 \9 D  W4 v' S! i
  50.        .WithLanguage(opt.Language);*/
    5 V( f: N" v( b+ a- d0 M$ D3 `
  51.     var builder = factory.CreateBuilder()
    6 X5 R2 f$ g' }5 `
  52.    .WithLanguage("english");
    : J# G" I$ {1 p3 p/ r" J9 S
  53.     using var processor = builder.Build();( E  x+ w6 f- v& n& Y

  54. ; A' Q5 L& L, Z7 o
  55.     using var fileStream = File.OpenRead(opt.FileName);
    + Q0 ?. X0 r+ V/ c

  56. 8 X4 U$ R# `! l' o7 u$ n* }- J
  57.     var wave = new WaveParser(fileStream);
    ; B' I. q; O9 {& L2 Z

  58. , I. `5 }- z) n& F
  59.     var samples = wave.GetAvgSamples();+ m+ c; S" N$ \3 J
  60.   e  c% r9 H+ J  W% W* c+ H
  61.     var language = processor.DetectLanguage(samples, speedUp: true);
    5 g- }  X& y8 d8 H" }  J" \
  62.     Console.WriteLine("Language is " + language);
    , n, G$ P- B& O1 y' z
  63. }* j; {; b- C- ~# l1 ]6 u
  64. ) G5 `: J, ?* Y- T7 ^
  65. async Task FullDetection(Options opt)2 z$ [6 j! j( a% i8 x
  66. {& h1 }' A/ |+ l  ?
  67.     // Same factory can be used by multiple task to create processors.
    ; X* M" l+ K: X5 Q8 P8 T
  68.     using var factory = WhisperFactory.FromPath(opt.ModelName);% T/ x; Z: |9 C! G1 b% m- R
  69. % E# m* o  x+ ~. S, q
  70.     //   var builder = factory.CreateBuilder().WithLanguage(opt.Language);% U* ?7 g" s% V9 a. o8 N
  71.     Console.WriteLine("请输入语言选项(例如:english,chinese, japanese等):");2 M) H( ]; }' ?4 o: @8 X
  72.     string languageOption = Console.ReadLine();
    1 C9 @/ d1 z, A0 z6 P, e1 u
  73.     var builder = factory.CreateBuilder()4 V9 v* T8 [9 n: M3 v5 {) D
  74.     .WithLanguage(languageOption).WithSpeedUp2x().WithThreads(16);7 c4 G" ^/ b; N0 a9 \5 a: T/ ]. K
  75. : `: Y  B6 J' Y* B: @8 F
  76.     if (opt.Command == "translate")) Z: k2 ]; ]0 y8 L
  77.     {
    1 g3 B# Y  V1 L* s( k
  78.         builder.WithTranslate();
    9 e- V' s* q/ i# k) F# J6 o
  79.     }+ q% E" R+ ~# c, W4 I1 S( s+ S& j4 z
  80. 6 E2 j: d5 k8 M( x% F$ M; |
  81.     WhisperProcessor processor = builder.Build();* ~7 q  H- T6 ?, a- G
  82.     + _  C+ |- l. U6 A- r. R7 C6 K
  83.     Console.WriteLine("请输入wave源文件目录:");4 D  f! D8 k! ~) Z2 n2 r: R
  84.     string sourceDirectory = Console.ReadLine();7 k9 P6 F0 v9 F+ O' N+ ?

  85. 0 _0 t$ a8 b; g2 l& Q( S
  86.     Console.WriteLine("请输入目标文件目录:");
      V& s1 v' e3 b* z2 Q* d
  87.     string targetDirectory = Console.ReadLine();
    8 p, N2 t: s1 v. B/ _

  88. & b- v  y. m3 L, }; z& \
  89.     if (!Directory.Exists(sourceDirectory) || !Directory.Exists(targetDirectory))
    : y7 n# d8 g- @4 W0 V$ u/ d
  90.     {' A0 ]1 D* k4 f# R( ]  E* n) k1 f* C
  91.         Console.WriteLine("目录不存在,请检查输入的目录路径。");9 }6 }3 g, u4 V+ X7 i. S- e
  92.         return;- c- W: C5 K- W8 V5 j! \6 l$ j
  93.     }$ A+ P- z* z8 }4 G, d! _; A

  94. : j3 |. v' f' q, S' @
  95.     await ProcessFilesAsync(processor ,sourceDirectory, targetDirectory);* p/ ]. D- g( Z9 N1 O

  96. ) L7 k2 X4 A+ I- w
  97.     Console.WriteLine("处理完成!");
    / J* y: R0 B+ E$ p4 V+ m

  98. 4 y$ j3 f( f: i  D" n7 [, f2 U% O
  99. }5 _$ T( |7 @7 _( |3 ~
  100. static async Task ProcessFilesAsync(WhisperProcessor processor,
    0 [% R+ ~8 Q' R+ V( L4 x
  101.     string sourceDirectory, string targetDirectory)
    " z" N& ?0 F% |+ Z1 _1 i8 |& i
  102. {
    $ `$ e7 H$ O' n* k/ W$ n6 P
  103.     var files = Directory.GetFiles(sourceDirectory, "*.wav", SearchOption.AllDirectories);: e: n- [( n6 P* J1 y

  104. % s, Y. a3 \$ D9 @4 T" k# z
  105.     foreach (var sourceFilePath in files)( e/ F( a( _2 }8 r3 A; c2 {
  106.     {  E% a  n3 g# p8 C9 I$ _& y
  107.         string relativePath = Path.GetRelativePath(sourceDirectory, sourceFilePath);
    % x: m& W! `: X& z, j$ Y
  108.         string destinationFilePath = Path.Combine(targetDirectory, relativePath);1 }, j6 h- F9 k! w
  109.         destinationFilePath = Path.ChangeExtension(destinationFilePath, ".srt");
    & [1 U, X' i  j" U
  110. 1 U- y3 {' }  n2 n$ S
  111.         Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath));
    8 j( j6 r6 y: G4 V2 x3 I6 O
  112.   {- e8 I& f; J; a) M
  113. 1 S9 l7 C! Z- K& L
  114.         if (!File.Exists(destinationFilePath))) c) H. J- o/ O9 l- l  j9 d$ Z& i' O. F# U
  115.         {$ b: z  c' T9 q3 J0 I! Q
  116.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;正在处理文件:{sourceFilePath}");) p; `4 @+ ~9 h. u6 x
  117. 0 P" c8 G4 U! Y5 r6 A5 e
  118.             using var fileStream = File.OpenRead(sourceFilePath);4 T9 D/ B0 M0 f6 N
  119.             var segmentIndex = 1;. r8 o  V8 q, t6 d1 m
  120.             using var writer = new StreamWriter(destinationFilePath); // 创建用于写入srt文件的StreamWriter
    7 c* V  C- b( K$ T$ u* o3 |1 q
  121.             var startTime = DateTime.Now; // 记录开始时间
    8 p" W( F5 E5 j" B' {1 \

  122. 5 R( K7 `' c1 e* u% m3 ?! f% N; j
  123.             await foreach (var segment in processor.ProcessAsync(fileStream, CancellationToken.None))
    / M1 M3 J) v' @, @
  124.             {
    ; p8 F1 _& }# z6 L5 s4 o6 Y9 X
  125.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    2 v* f% [+ w- T! n
  126.                 Console.WriteLine([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");
    : B# P1 Z# M  e* a) O( Y% M8 ?
  127.                 Console.WriteLine(segment.Text);
    * ]: \9 `7 ^5 X# q% K2 Y! a
  128.                 Console.WriteLine();$ q9 F' a0 _$ x4 A% |
  129. " |& p4 s6 l4 ^0 U
  130.                 // 将srt内容写入文件
    7 Q$ T" t- R' S- a; l. B, z2 c
  131.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segmentIndex}");
    8 Z8 {! j7 Y$ K( o+ C
  132.                 await writer.WriteLineAsync([        DISCUZ_CODE_1        ]quot;{segment.Start:hh\\:mm\\:ss\\,fff} --> {segment.End:hh\\:mm\\:ss\\,fff}");; A: r6 F0 Y; k6 y
  133.                 await writer.WriteLineAsync(segment.Text);
    3 J" r1 r2 C  C& {; T" p
  134.                 await writer.WriteLineAsync();- M! @+ S3 G1 D' @
  135. % c/ x! u; t$ a/ j# M) l) A
  136.                 writer.Flush(); // 立即保存srt文件
      m% U: S: V) {
  137. : B  u$ H% X( J& c1 r
  138.                 segmentIndex++;
    2 [7 a' N9 x* ]/ Y2 L( y; R0 ^
  139.             }
    2 M8 H$ t4 E- i, e( [- J

  140. + y, x( i7 T1 ?4 `0 f' |$ s6 g
  141.             var endTime = DateTime.Now; // 记录结束时间4 R& ^! }; l* B# q" O( A4 z, s
  142.             var elapsedMinutes = (endTime - startTime).TotalMinutes;
      l3 M8 F* ~: r4 [
  143.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;已生成srt文件:{destinationFilePath}");
    * {7 Z5 v! O% a' i/ y
  144.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;生成耗费时间:{elapsedMinutes} 分钟");
    $ d( W5 A0 V8 r( }' z# S8 X
  145.         }
    4 h+ b' ?! D' _( G/ N7 }/ X8 X* f
  146.         else {! v6 _9 `" H% p9 Z) T
  147.             Console.WriteLine([        DISCUZ_CODE_1        ]quot;srt文件已经存在:{destinationFilePath}");9 x( a# V) d8 I
  148.         }; q7 p  X, [& F7 G
  149.     }8 o7 `8 q# t$ s8 H% l
  150. }
    ) C+ W+ ~# r7 }: m1 D8 Y; n  d
  151. public class Options) N6 _+ S8 o( i& u, g# x1 W
  152. {
    . h( m: R& b: ?, Z: V6 I
  153.     [Option('t', "command", Required = false, HelpText = "Command to run (lang-detect, transcribe or translate)", Default = "transcribe")]
    / `# o/ {% ~4 w8 e/ a3 u& I
  154.     public string Command { get; set; }, ~# t( z# a3 B  g* I$ C6 R
  155. 4 Q7 J% [$ W& J
  156.     [Option('f', "file", Required = false, HelpText = "File to process", Default = "test.mp3")]7 W. }+ v2 \8 D9 v7 P) |. {
  157.     public string FileName { get; set; }' U7 U9 f" ?' P, z' m

  158. & y5 C; U& }. }* H
  159.     [Option('l', "lang", Required = false, HelpText = "Language", Default = "auto")]
    6 h4 C- Y( O  }: M( S- w
  160.     public string Language { get; set; }, b: ?9 B& R3 x8 N! L/ d) T6 C: A0 w
  161. ' ?" E) T- ^. _# W0 u8 v: ^
  162.     [Option('m', "modelFile", Required = false, HelpText = "Model to use (filename", Default = "ggml-large.bin")]! B8 N) a2 ?/ K! W
  163.     public string ModelName { get; set; }
    # }( M$ d* T3 M$ B$ _
  164. : n/ ]& l/ k+ V4 L- |. K1 Y7 U
  165.     [Option('g', "ggml", Required = false, HelpText = "Ggml Model type to download (if not exists)", Default = GgmlType.Base)]
    3 b% Y  x) M0 G& e
  166.     public GgmlType ModelType { get; set; }$ \$ o, I8 q& E* }" e5 ^
  167. }/ t2 w& [" t* T+ }& D# C4 u
复制代码
' n, _' e( R  I, O) `: _
, x* h. I) S% e

' z2 k9 t; `- G, x4 H2 n7 @% f$ 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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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