File size: 40,576 Bytes
3f9bd99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
import shutil
import gradio as gr
import os
import webbrowser
import subprocess
import json
import yaml
import argparse

#########################################################
py_dir=r"venv\python.exe" # SET PYTHON PATH HERE!
#########################################################


current_directory = os.path.dirname(os.path.abspath(__file__))
if not os.path.exists('./Data'):
    os.mkdir('./Data')
 
################### Load md
try:
   with open('docs/file_structure.md', mode="r", encoding="utf-8") as f:
       file_structure_md=f.read()
except Exception as e:
    file_structure_md='读取错误'+ str(e)
try:
   with open('docs/README.md', mode="r", encoding="utf-8") as f:
       readme_md=f.read()
except Exception as e:
    readme_md='读取错误'+ str(e)    
try:
   with open('docs/command_usage.md', mode="r", encoding="utf-8") as f:
       cmd_md=f.read()
except Exception as e:
    cmd_md='读取错误'+ str(e)       
try:
   with open('docs/update_info.md', mode="r", encoding="utf-8") as f:
       update_info=f.read()
except Exception as e:
    update_info='读取错误'+ str(e)       
try:
   with open('docs/errors.md', mode="r", encoding="utf-8") as f:
       errors=f.read()
except Exception as e:
    errors='读取错误'+ str(e)    
###################

current_page=1
class_info={}
emo_speaker_list=[]
emo_class_list=[]
emo_file_name_list=[]
emo_audio_list=[]
emo_tr_list=[]
emo_checkbox_list=[]
emo_current_proj_name=None
def load_emo_clu(proj_name):
    if proj_name=="" or proj_name=='null':
        return "请选择!",emo_speaker.update(choices=[],value=None)
    global emo_current_proj_name
    global class_info
    global emo_speaker_list
    emo_current_proj_name=proj_name
    
    try:
        class_info = yaml.load(open(os.path.join('Data',proj_name,'emo_clustering.yml')),Loader=yaml.FullLoader)
        emo_speaker_list=list(class_info.keys())
        return emo_status_text.update(value=f"当前的实验:{proj_name}"),emo_speaker.update(choices=emo_speaker_list,value=emo_speaker_list[0])#,*emo_change_speaker(emo_speaker_list[0])#,*load_page(emo_speaker_list[0],list(class_info[emo_speaker_list[0]].keys())[0])
    except Exception as e:
        class_info={}
        emo_speaker_list=[]
        return emo_status_text.update(value='加载错误'+str(e)),emo_speaker.update(choices=[],value=None)

def get_transcription(proj_name,spk,wav):#transciption and wav path
    y=yaml.load(open(os.path.join('Data',proj_name,'config.yml')),Loader=yaml.FullLoader)
    wav_path=os.path.normpath(os.path.join(y["dataset_path"],y["resample"]["out_dir"],spk,wav))
    list_path=os.path.join(y["dataset_path"],y["preprocess_text"]["cleaned_path"])
    with open(list_path, mode="r", encoding="utf-8", errors='ignore') as f:
        for lines in f:
            if os.path.normpath(lines.split("|")[0])==wav_path:
                return lines.split("|")[3],wav_path
        return "加载失败",""


def emo_change_speaker(speaker): 
    if speaker is None:
        return emo_chosen_class.update(choices=[],value=None)
    global current_page
    current_page=1
    lst=list(class_info[speaker].keys())
    return emo_chosen_class.update(choices=lst,value=lst[0]),*switch_page(speaker,lst[0])

def emo_change_class(speaker,class_):
    if (speaker is None) or (class_ is None):
        return emo_ret_none()
    global current_page
    current_page=1
    return switch_page(speaker,class_)

def emo_ret_none():
    global current_page
    wavname_list=[]
    transcription_list=[]
    audio_list=[]
    checkbox_list=[]
    for i in range(10):
        wavname_list.append(gr.Textbox().update(value=None,label='None',visible=False))
        audio_list.append(gr.Audio.update(label="情感参考音频",value=None,interactive=False,visible=False))
        transcription_list.append(gr.Textbox().update(value=None,visible=False))
        checkbox_list.append(gr.Checkbox().update(value=False,visible=False))
    wavname_list[0]=gr.Textbox().update(value='看起来列表似乎是空的',label='None',visible=True)
    list_all=wavname_list+transcription_list+audio_list+checkbox_list
    return *list_all,previous_btn.update(interactive=False),emo_page_index.update(value=current_page),next_btn.update(interactive=False)

def load_page(page_start,page_end,spk,class_name):#load lines of content
    global emo_current_proj_name
    wavname_list=[]
    transcription_list=[]
    audio_list=[]
    checkbox_list=[]
    #page_start,page_end,_,_=calculate_page(spk,class_name)
    for i in range(page_start, page_end+1):
        wav_name=class_info[spk][class_name][i]
        tr,wavpath=get_transcription(emo_current_proj_name,spk,wav_name)
        if wavpath=="":
           audio_list.append(gr.Audio.update(label="情感参考音频",value=None,interactive=False,visible=True)) 
        else:
           audio_list.append(gr.Audio.update(label="情感参考音频",value=wavpath,interactive=False,visible=True)) 
        wavname_list.append(gr.Textbox().update(value=wav_name,label=i,visible=True))        
        transcription_list.append(gr.Textbox().update(value=tr,visible=True))
        checkbox_list.append(gr.Checkbox().update(value=False,visible=True))
    length=page_end-page_start
    if length<10:
        for i in range(9-length):
            wavname_list.append(gr.Textbox().update(value=None,label='None',visible=False))
            audio_list.append(gr.Audio.update(label="情感参考音频",value=None,interactive=False,visible=False))
            transcription_list.append(gr.Textbox().update(value=None,visible=False))
            checkbox_list.append(gr.Checkbox().update(value=False,visible=False))
    list_all=wavname_list+transcription_list+audio_list+checkbox_list
    return list_all

def calculate_page(length):#calculate the index and return
    global current_page
    if length<=10 and current_page==1:
        return 0,length-1,False,False#range,left,right
    else:
        end=10*current_page-1
        if end > length-1:#num<10
           end=length-1
           return 10*(current_page-1),end,True,False
        else:#full
           if current_page==1:
              return 10*(current_page-1),end,False,True 
           return 10*(current_page-1),end,True,True

def switch_page(speaker,class_name):#switch to the specified page or adjust page index , then load page.
    global current_page
    global class_info
    if current_page<1:
        current_page=1
    length=len(class_info[speaker][class_name])
    if length==0:
        return emo_ret_none()
    if current_page>1 and (current_page-1)*10>=length:#e.g [0-9],page==2-> [10] -> out of range
        current_page-=1
    #print(length)
    page_start,page_end,left,right=calculate_page(length)
    #print(page_start,page_end)
    return *load_page(page_start,page_end,speaker,class_name),previous_btn.update(interactive=left),emo_page_index.update(value=current_page),next_btn.update(interactive=right)

def reverse_selection(*checkbox_list):
    rt_list = [not i if i is True else True for i in checkbox_list]
    return rt_list

def del_wav_in_class(speaker,class_name,*checkbox_list):
    length=len(class_info[speaker][class_name])
    page_start,page_end,_,_=calculate_page(length)
    id=0
    checkbox_list=list(checkbox_list)
    for i in range(page_start, page_end+1):
        if checkbox_list[id]:
            class_info[speaker][class_name][id]=None
        id+=1
    while None in class_info[speaker][class_name]:
        class_info[speaker][class_name].remove(None)
    return switch_page(speaker,class_name)

def del_rename_class(speaker,class_,new_name=None):
    global class_info
    global current_page
    if new_name is not None:
        if new_name in class_info[speaker]:
            return emo_chosen_class.update(value=new_name,choices=list(class_info[speaker].keys())),gr.Textbox().update(placeholder='重名了!',value=None)
        class_info[speaker][new_name]=class_info[speaker][class_]
        del class_info[speaker][class_]
        return emo_chosen_class.update(value=new_name,choices=list(class_info[speaker].keys())),gr.Textbox().update(placeholder='输入重命名',value=None)
    else:
        del class_info[speaker][class_]
        lst=list(class_info[speaker].keys())
        current_page=0
        return emo_chosen_class.update(choices=lst,value=lst[0])      



current_yml=None
def get_status():
    global current_yml
    try:
        cfg = yaml.load(open('config.yml'),Loader=yaml.FullLoader)
        current_yml='当前的训练: '+os.path.basename(cfg["dataset_path"])+"\n\n以下是配置文件内容:\n\n"
        with open('config.yml', mode="r", encoding="utf-8", errors='ignore') as f:
            current_y=f.read()
            current_yml+=current_y
    except Exception as error:
        current_yml=error

get_status()

def p0_write_yml(name,val_per_spk,max_val_total,bert_num_processes,emo_num_processes,num_workers,keep_ckpts):
    if name=='null'or name=='':
        return '请选择!'
    config_path=os.path.join('Data',name,'config.yml')
    config_yml = yaml.load(open(config_path),Loader=yaml.FullLoader)
    config_yml["preprocess_text"]["val_per_spk"] = int(val_per_spk)
    config_yml["preprocess_text"]["max_val_total"] = int(max_val_total)
    config_yml["bert_gen"]["num_processes"] = int(bert_num_processes)
    config_yml["emo_gen"]["num_processes"] = int(emo_num_processes)
    config_yml["train_ms"]["num_workers"]=int(num_workers)
    config_yml["train_ms"]["keep_ckpts"]=int(keep_ckpts)
    with open(config_path, 'w', encoding='utf-8') as f:
          yaml.dump(config_yml, f) 
    return 'Success'


list_project = []  
def refresh_project_list():
    global list_project
    list_project = []  
    for item in os.listdir('Data'):
       item_path = os.path.join('Data', item)
       if os.path.isdir(item_path):
          list_project.append(item)
    return (project_name.update(choices=list_project),project_name2.update(choices=list_project),project_name3.update(choices=list_project),project_name4.update(choices=list_project),'已刷新下拉列表')

for item in os.listdir('Data'):
    item_path = os.path.join('Data', item)
    if os.path.isdir(item_path):
        list_project.append(item)



def p0_mkdir(name):
    if name!='':
       try:   
         path='Data'
         path=os.path.join('Data',name)  
         os.mkdir(path)#path=data/xxx/
         os.mkdir(os.path.join(path,'custom_character_voice'))
         os.mkdir(os.path.join(path,'filelists'))
         os.mkdir(os.path.join(path,'models'))       
         shutil.copy("./configs/config.json",os.path.join(path,"config.json"))
         try:
            with open('./configs/default_config.yml', mode="r", encoding="utf-8") as f:
                cfg_yml=yaml.load(f,Loader=yaml.FullLoader)
         except:
            with open('default_config.yml', mode="r", encoding="utf-8") as f:
                cfg_yml=yaml.load(f,Loader=yaml.FullLoader)
         cfg_yml["dataset_path"]=path
         cfg_yml["resample"]["in_dir"]="custom_character_voice"
         cfg_yml["resample"]["out_dir"]="custom_character_voice"
         cfg_yml["preprocess_text"]["cleaned_path"]='filelists/cleaned.list'
         cfg_yml["preprocess_text"]["transcription_path"]='filelists/short_character_anno.list'
         cfg_yml["preprocess_text"]["train_path"]='filelists/train.list'
         cfg_yml["preprocess_text"]["val_path"]='filelists/val.list'
         cfg_yml["preprocess_text"]["config_path"]='config.json'
         cfg_yml["bert_gen"]["config_path"]='config.json'
         cfg_yml["emo_gen"]["config_path"]='config.json'
         cfg_yml["train_ms"]["config_path"]='config.json'
         with open(os.path.join(path,"config.yml"), 'w', encoding='utf-8') as f:
            yaml.dump(cfg_yml, f) 
         os.startfile(path)
         refresh_project_list()
         return project_name.update(choices=list_project,value=name),'Success. 已经自动打开了创建好的文件夹。请将音频按说话人分文件夹放入custom_character_voice内。然后进行下一步操作。'
       except Exception as error:
         return error   
    else:
       return '请输入名称!'    

def p0_load_cfg(projectname):
    if projectname=='null'or projectname=='':
        return p0_status.update(value=current_yml),'请选择!'
    try:
        shutil.copy(os.path.join('Data',projectname,'config.yml'),'config.yml')
        get_status()
        return p0_status.update(value=current_yml) ,'Success'
    except Exception as error:
        return p0_status.update(value=current_yml),error

        


def a1a_transcribe(size,lang):
     command = f'{py_dir} short_audio_transcribe.py --languages {lang} --whisper_size {size}'
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。完成后无报错即可关闭进行下一步!'

def a1b_transcribe_genshin():
     command = f"{py_dir} transcribe_genshin.py"
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。完成后无报错即可关闭进行下一步!'

def a2_preprocess_text():
     command = f"{py_dir} preprocess_text.py"
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。完成后无报错即可关闭进行下一步!'

def a3_bert_gen():
     command = f"{py_dir} bert_gen.py"
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。完成后无报错即可关闭进行下一步!'

def a3_emo_gen():
    command = f"{py_dir} emo_gen.py"
    print(command+'\n\n')
    subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
    return '新的命令行窗口已经打开,请关注输出信息。完成后无报错即可关闭进行下一步!'

def a35_json(bs,lr,interval):
    try:
        with open('config.yml', mode="r", encoding="utf-8") as f:
            cfg_yml=yaml.load(f,Loader=yaml.FullLoader)
        config_path=os.path.join(cfg_yml["dataset_path"],'config.json')
        configjson = json.load(open(config_path, encoding="utf-8"))
        configjson["train"]["batch_size"] = int(bs)
        configjson["train"]["learning_rate"] = lr
        configjson["train"]["log_interval"] = int(interval)
        configjson["train"]['eval_interval'] = int(interval)
        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(configjson, f, indent=2, ensure_ascii=False) 
        return 'success'
    except Exception as error:
        return error 
    
        
def a4a_train():
     command = f"{py_dir} train_ms.py"
     with open('config.yml', mode="r", encoding="utf-8") as f:
          configyml=yaml.load(f,Loader=yaml.FullLoader)
     cfg_path=os.path.join(configyml["dataset_path"],'config.json')        
     configjson = json.load(open(cfg_path, encoding="utf-8"))
     if not configjson["train"]["skip_optimizer"]:
         configjson["train"]["skip_optimizer"]=True
         with open(cfg_path, 'w', encoding='utf-8') as f:
             json.dump(configjson, f, indent=2, ensure_ascii=False)
         print("已经修改配置文件!\n")
     shutil.copy('./pretrained_models/D_0.pth',os.path.join(os.path.join(configyml["dataset_path"],configyml["train_ms"]["model"]),'D_0.pth'))
     shutil.copy('./pretrained_models/G_0.pth',os.path.join(os.path.join(configyml["dataset_path"],configyml["train_ms"]["model"]),'G_0.pth'))
     shutil.copy('./pretrained_models/DUR_0.pth',os.path.join(os.path.join(configyml["dataset_path"],configyml["train_ms"]["model"]),'DUR_0.pth'))
     print("已经复制了底模\n")
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     print(command+'\n\n')
     return '新的命令行窗口已经打开,请关注输出信息。关闭窗口或Ctrl+C终止训练'

def a4b_train_cont():
     command = f"{py_dir} train_ms.py"
     with open('config.yml', mode="r", encoding="utf-8") as f:
            configyml=yaml.load(f,Loader=yaml.FullLoader)
     cfg_path=os.path.join(configyml["dataset_path"],'config.json')   
     configjson = json.load(open(cfg_path, encoding="utf-8"))
     if configjson["train"]["skip_optimizer"]:
         configjson["train"]["skip_optimizer"]=False
         with open(cfg_path, 'w', encoding='utf-8') as f:
             json.dump(configjson, f, indent=2, ensure_ascii=False)
         print("已经修改配置文件!\n")
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     print(command+'\n\n')
     return '新的命令行窗口已经打开,请关注输出信息。关闭窗口或Ctrl+C终止训练'

def start_tb():
     with open('config.yml', mode="r", encoding="utf-8") as f:
            configyml=yaml.load(f,Loader=yaml.FullLoader)
     command = f"{py_dir} -m tensorboard.main --logdir="+os.path.join(configyml["dataset_path"],configyml["train_ms"]["model"])
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。'

ckpt_list = ['null']

def c2_refresh_sub_opt(name):  
   try:
       global ckpt_list
       ckpt_list=['null']
       file_list = os.listdir(os.path.join("Data",name,"models"))
       for ck in file_list:
         if os.path.splitext(ck)[-1] == ".pth"and ck[:2] != "D_" and ck[:4] !="DUR_":
            ckpt_list.append(ck)
       return models_in_project.update(choices=ckpt_list,value=ckpt_list[-1])
   except :
       return models_in_project.update(choices=['null'],value='null')

def c2_infer(proj_name,model_name):
    if proj_name=='null' or model_name=='null':
        return '请选择模型!'
   
    path=f'./Data/{proj_name}'
    command = f'{py_dir} webui.py -c {path}/config.json -m {path}/models/{model_name}'
    print(command+'\n\n')
    subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
    return '新的命令行窗口已经打开,请关注输出信息。关闭窗口结束推理服务。'

def c2_infer_2(proj_name,model_name):
    y=yaml.load(open('config.yml'),Loader=yaml.FullLoader)
    if proj_name=='null' or model_name=='null':
        y["server"]["models"]=[]
    else:
        y["server"]["models"]=[]
        y["server"]["models"].append({"config":os.path.join('Data',proj_name,'config.json'),"device":'cuda',"language": 'ZH',"model":os.path.join('Data',proj_name,'models',model_name),"speakers":[]})
    with open("config.yml", 'w', encoding='utf-8') as f:
        yaml.dump(y, f) 
    subprocess.Popen(['start', 'cmd', '/k',f'{py_dir} server_fastapi.py'],cwd=current_directory,shell=True)
    return '已经修改了全局配置文件。新的命令行窗口已经打开,请关注输出信息。关闭窗口结束推理服务。'

def write_version(name,version,cont):
    if name=='null':
        return opt_continue.update(value=False),'请选择!'
    path=os.path.join('Data',name,'config.json')
    try:
       configjson = json.load(open(path))
       if "version" in configjson:
          if not cont:
            return opt_continue.update(value=False),'版本信息已经存在,是不是手滑了?'
          configjson["version"] = version
       else:
           configjson["version"] = version
       with open(path, 'w', encoding='utf-8') as f:
            json.dump(configjson, f, indent=2, ensure_ascii=False) 
       return opt_continue.update(value=False),f'Success. {version}'
    except Exception as e:
       return opt_continue.update(value=False),e

def switch_previous_page(speaker,class_name):
    global current_page
    current_page-=1
    return switch_page(speaker,class_name)
def switch_next_page(speaker,class_name):
    global current_page
    current_page+=1
    return switch_page(speaker,class_name)

def emo_write(proj_name):
    global class_info
    try:
        with open(os.path.join('Data',proj_name,'emo_clustering.yml'), 'w', encoding='utf-8') as f:
            yaml.dump(class_info, f) 
        return 'Success'
    except Exception as e:
        return '写入出错'+str(e)

def run_ec_gen(proj_name,num_clusters,num_wav):
     if proj_name=="":
        command = f"{py_dir} emotion_clustering.py -n {int(num_clusters)} -r {int(num_wav)}"
     else:
        command = f"{py_dir} emotion_clustering.py -y {os.path.join('Data',proj_name,'config.yml')} -n {int(num_clusters)} -r {int(num_wav)}" 
     print(command+'\n\n')
     subprocess.Popen(['start', 'cmd', '/k', command],cwd=current_directory,shell=True)
     return '新的命令行窗口已经打开,请关注输出信息。'

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-p", "--server_port", default=6660,type=int,help="server_port"
    )
    args = parser.parse_args()
    with gr.Blocks(title="Bert-VITS-2-Manager-WebUI-210") as app:
        gr.Markdown(value="""
        Bert-VITS2训练管理器
                    
        严禁将此项目用于一切违反《中华人民共和国宪法》,《中华人民共和国刑法》,《中华人民共和国治安管理处罚法》和《中华人民共和国民法典》之用途。由使用本整合包产生的问题和作者、原作者无关!!!
        
        作者:bilibili@数列解析几何一生之敌
        
        适用于整合包版本V2.1,不兼容之前的版本。
                    
        WebUI更新日期:2023.11.30
        """) 
        with gr.Tabs():
           with gr.TabItem("1.创建实验文件夹和加载全局配置"):
               with gr.Row(): 
                   with gr.Column():
                       p0_mkdir_name=gr.Textbox(label="这将创建实验文件夹,请输入实验名称,不要包含中文、特殊字符和保留字符。",
                       placeholder="请输入实验名称,最好不要包含中文、特殊字符和保留字符。",
                       value="",
                       lines=1,
                       interactive=True)                       
                       p0_mkdir_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)
                       p0_mkdir_btn=gr.Button(value="创建!", variant="primary")

                       gr.Markdown(value="<br>")
                                                     
                       project_name = gr.Dropdown(label="实验文件夹", choices=list_project, value='null'if not list_project else list_project[-1],interactive=True) 
                       with gr.Row():
                            p0_val_ps = gr.Number(label="每个说话人的验证集数", value="4",interactive=True)
                            p0_val_tt = gr.Number(label="总的验证集数", value="8",interactive=True)
                            p0_bg_t = gr.Number(label="bert_gen线程数", value="2",interactive=True)
                            p0_emo_t = gr.Number(label="emo_gen线程数", value="2",interactive=True)
                            p0_dataloader = gr.Number(label="num_workers", value="4",interactive=True)
                            p0_keep_ckpt = gr.Number(label="模型留存个数", value="10",interactive=True)
                       p0_load_cfg_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)
                       with gr.Row():
                          p0_write_cfg_btn=gr.Button(value="保存更改(但不会自动加载)", variant="primary")
                          p0_load_cfg_btn = gr.Button(value="加载训练配置", variant="primary")
                          p0_load_cfg_refresh_btn=gr.Button(value="刷新选项", variant="secondary")


                   with gr.Column():
                       #p0_current_proj=gr.Textbox(label="当前生效的训练",value="",interactive=False)
                       p0_status=gr.TextArea(label="训练前请确认当前的全局配置信息", value=current_yml,interactive=False)

           with gr.TabItem("2.训练"):
               with gr.Column():                                 
                   whisper_size = gr.Radio(label="选择whisper大小,large需要12G显存", choices=['large','medium','small'], value="medium")
                   language = gr.Radio(label="选择语言(默认中日英,其他不支持的语言会被跳过)", choices=['C','CJ','CJE'], value="CJE") 
               with gr.Column():
                    with gr.Row():
                        a1a_btn = gr.Button(value="1.a.数据集重采样和标注(使用whisper)", variant="primary")
                        a1b_btn = gr.Button(value="1.b.处理下载的已标注的原神数据集", variant="primary") 
                    a1_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮,二选一",interactive=False)                
               #gr.Markdown(value="<br>")      
               with gr.Row():
                    a2_btn = gr.Button(value="2.文本预处理", variant="primary")
                    a2_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)
               #gr.Markdown(value="<br>") 
               with gr.Row():
                  a3_btn = gr.Button(value="3-1.生成bert文件", variant="primary")
                  a3_btn_2 = gr.Button(value="3-2.生成emo文件", variant="primary")
                  a3_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)                                  
              # gr.Markdown(value="<br>") 
               with gr.Row():
                    #with gr.Column():
                    a35_btn = gr.Button(value="写入配置文件", variant="primary")
                    with gr.Column():
                        with gr.Row():
                            a35_textbox_bs = gr.Number(label="批大小", value="8",interactive=True)
                            a35_textbox_lr = gr.Number(label="学习率", value="0.0001",interactive=True)
                            a35_textbox_save = gr.Number(label="保存间隔", value="100",interactive=True)
                        a35_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False) 
               #gr.Markdown(value="<br>") 
               with gr.Row():              
                    with gr.Row():
                       a4a_btn = gr.Button(value="4a.首次训练", variant="primary")
                       a4b_btn = gr.Button(value="4b.继续训练", variant="primary")                       
                    with gr.Column():
                       a4_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)
        
               with gr.Row():              
                       tb_btn = gr.Button(value="启动TensorBoard", variant="primary")            
                       tb_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)                   
           with gr.TabItem("3.启动推理"):
                gr.Markdown(value='工作区模型推理(Data内各实验目录下的模型)') 
                with gr.Row():
                    project_name2 = gr.Dropdown(label="选择实验名", choices=list_project, value='null',interactive=True)
                    models_in_project = gr.Dropdown(label="选择模型", choices=ckpt_list, value='null'if not ckpt_list else ckpt_list[0],interactive=True)
                    with gr.Column():
                       c2_btn = gr.Button(value="启动推理(Gr WebUI)", variant="primary")
                       c2_btn2 = gr.Button(value="启动推理(Hiyori UI)", variant="primary")
                       c2_btn_refresh=gr.Button(value="刷新选项", variant="secondary")
                with gr.Column():
                       c2_textbox_output_text = gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False) 
                project_name2.change(c2_refresh_sub_opt,[project_name2],[models_in_project]) 
           with gr.TabItem("辅助功能"):
                with gr.TabItem("情感分类编辑"):
                    with gr.Row():
                        project_name4=gr.Dropdown(label="选择实验名", choices=list_project,value=''if not list_project else list_project[0],interactive=True)
                        emo_proj_load_btn=gr.Button(value="加载配置", variant="primary")
                        emo_proj_refresh=gr.Button(value="刷新选项", variant="secondary")
                    emo_status_text=gr.Textbox(label="状态", placeholder="点击处理按钮",interactive=False)
                #   
                    with gr.Column():
                        with gr.Row():
                            emo_speaker=gr.Dropdown(label='选择说话人',choices=emo_speaker_list,interactive=True)
                            emo_chosen_class=gr.Dropdown(label='选择类别',choices=emo_class_list,interactive=True)
                            emo_write_btn=gr.Button(value="写入(保存更改)", variant="primary")
                        with gr.Accordion("生成配置"):
                            with gr.Row():
                                ec_gen_btn=gr.Button(value="生成配置",variant="primary")
                                ec_gen_n_clu=gr.Number(label="类别数量",value=5)
                                ec_gen_range=gr.Number(label="每类的音频数",value=5)                    
                        with gr.Accordion("编辑区域"):
                            with gr.Row():                                
                                emo_enter_rename=gr.Textbox(label="重命名",placeholder="在此输入重命名,然后点击重命名按钮",scale=2)
                                emo_enter_rename_btn=gr.Button(value="重命名类别", variant="primary",scale=1)
                                emo_del_class_btn=gr.Button(value="删除此类别", variant="primary",scale=1)
                                emo_del_wav_btn=gr.Button(value="删除所选", variant="primary",scale=1)
                                emo_reverse_selection_btn=gr.Button(value="反向选择", variant="primary",scale=1)
                        with gr.Row():
                                emo_file_name=gr.Textbox(label="文件名",value='空列表',interactive=False,scale=4)
                                emo_tr=gr.Textbox(label="文本",value=None,interactive=False,scale=5,visible=False)
                                emo_wav=gr.Audio(label="情感参考音频",value=None,interactive=False,visible=False,scale=5)
                                emo_checkbox=gr.Checkbox(label='选择',value=False,scale=1,visible=False)
                                emo_tr_list.append(emo_tr)
                                emo_file_name_list.append(emo_file_name)
                                emo_audio_list.append(emo_wav)
                                emo_checkbox_list.append(emo_checkbox)
                        for i in range(9):
                            with gr.Row():
                                emo_file_name=gr.Textbox(label="文件名",value=None,interactive=False,scale=4,visible=False)
                                emo_tr=gr.Textbox(label="文本",value=None,interactive=False,scale=5,visible=False)
                                emo_wav=gr.Audio(label="情感参考音频",value=None,interactive=False,visible=False,scale=5)
                                emo_checkbox=gr.Checkbox(label='选择',value=False,scale=1,visible=False)
                                emo_tr_list.append(emo_tr)
                                emo_file_name_list.append(emo_file_name)
                                emo_audio_list.append(emo_wav)
                                emo_checkbox_list.append(emo_checkbox)
                        with gr.Row():
                            previous_btn=gr.Button(value="<-上一页", variant="secondary",interactive=False,scale=5)
                            emo_page_index=gr.Number(label='页码',value=current_page,interactive=False,scale=1)
                            next_btn=gr.Button(value="下一页->", variant="primary",interactive=False,scale=5)
                        emo_speaker.change(emo_change_speaker,[emo_speaker],[emo_chosen_class,*emo_file_name_list,*emo_tr_list,*emo_audio_list,*emo_checkbox_list,previous_btn,emo_page_index,next_btn])
                        emo_chosen_class.change(emo_change_class,[emo_speaker,emo_chosen_class],[*emo_file_name_list,*emo_tr_list,*emo_audio_list,*emo_checkbox_list,previous_btn,emo_page_index,next_btn])
                with gr.TabItem("配置文件添加版本号"):
                    gr.Markdown(value='旧版本模型的配置文件添加版本号后方可在2.0版本下使用兼容推理')
                    gr.Markdown(value='按文件结构把配置文件和模型放到对应位置,然后开始操作。')
                    gr.Markdown(value='使用1.1和1.1.1版兼容推理需要安装上一个版本使用的日语bert。')
                    gr.Markdown(value='可选版本为1.0.1,1.1,1.1.1和2.0。旧整合包版本为1.0.1或1.1.1或2.0。')
                    project_name3 = gr.Dropdown(label="选择实验名", choices=list_project, value='null'if not list_project else list_project[0],interactive=True)
                    with gr.Row():
                      with gr.Column():
                          choose_version=gr.Dropdown(label="选择版本", choices=['1.0.1','1.1','1.1.1','2.0','2.1'], value='1.0.1',interactive=True)
                          opt_continue = gr.Checkbox(label="我没手滑")
                          write_ver_btn=gr.Button(value="写入",variant="primary")
                          write_ver_refresh_btn=gr.Button(value="刷新",variant="secondary")
                      with gr.Column():
                          write_ver_textbox=gr.Textbox(label="输出信息", placeholder="点击处理按钮",interactive=False)
           with gr.TabItem("关于&帮助"):
                with gr.TabItem("项目简介"):
                    with gr.Row():            
                        gr.Markdown(value=readme_md)
                        gr.Markdown(value=update_info)
                with gr.TabItem("训练流程和命令行使用"): 
                    with gr.Row():                  
                        gr.Markdown(value=cmd_md)                      
                        gr.Markdown(value=file_structure_md)
                with gr.TabItem("常见错误"):
                    with gr.Row():
                        gr.Markdown(value=errors)

        p0_write_cfg_btn.click(p0_write_yml,
                           inputs=[project_name,p0_val_ps,p0_val_tt,p0_bg_t,p0_emo_t,p0_dataloader,p0_keep_ckpt],
                           outputs=[
                p0_load_cfg_output_text,
            ],)                
        p0_mkdir_btn.click(p0_mkdir,
                           inputs=[p0_mkdir_name],
                           outputs=[
                               project_name,
                p0_mkdir_output_text,
            ],)
        p0_load_cfg_btn.click(p0_load_cfg,
                           inputs=[project_name],
                           outputs=[p0_status,
                p0_load_cfg_output_text,
            ],)
        p0_load_cfg_refresh_btn.click(refresh_project_list,
                           inputs=[],
                           outputs=[project_name,
                                    project_name2,
                                    project_name3,
                                    project_name4,
                p0_load_cfg_output_text,
            ],)
        emo_proj_refresh.click(refresh_project_list,
                           inputs=[],
                           outputs=[project_name,
                                    project_name2,
                                    project_name3,
                                    project_name4,
                emo_status_text,
            ],)        
        a1a_btn.click(
            a1a_transcribe,
            inputs=[whisper_size,language],
            outputs=[
                a1_textbox_output_text,
            ],
        )
 
        a1b_btn.click(
            a1b_transcribe_genshin,
            outputs=[
                a1_textbox_output_text,
            ],
        )
        
        a2_btn.click(
            a2_preprocess_text,
            outputs=[
                a2_textbox_output_text,
            ],
        )
        
        a3_btn.click(
            a3_bert_gen,
            outputs=[
                a3_textbox_output_text,
            ],
        )
        a3_btn_2.click(
            a3_emo_gen,
            outputs=[
                a3_textbox_output_text,
            ],
        )        
        a35_btn.click(
            a35_json,
            inputs=[a35_textbox_bs,a35_textbox_lr,a35_textbox_save],
            outputs=[
                a35_textbox_output_text,
            ],
        )
        a4a_btn.click(
            a4a_train,
            outputs=[
                a4_textbox_output_text,
            ],
        )
        a4b_btn.click(
            a4b_train_cont,
            outputs=[
                a4_textbox_output_text,
            ],
        ) 
        tb_btn.click(
            start_tb,
            outputs=[
                tb_textbox_output_text,
            ],
        )
        c2_btn.click(
            c2_infer,
            inputs=[project_name2,models_in_project],
            outputs=[
                c2_textbox_output_text,
            ],
        )
        c2_btn2.click(
            c2_infer_2,
            inputs=[project_name2,models_in_project],
            outputs=[
                c2_textbox_output_text,
            ],
        )            
        c2_btn_refresh.click(refresh_project_list,[],[project_name,project_name2,project_name3,project_name4,c2_textbox_output_text])
        write_ver_refresh_btn.click(refresh_project_list,[],[project_name,project_name2,project_name3,project_name4,write_ver_textbox])
        write_ver_btn.click(
            write_version,
            inputs=[project_name3,choose_version,opt_continue],
            outputs=[opt_continue,
                write_ver_textbox,
            ],
        ) 
        emo_proj_load_btn.click(load_emo_clu,inputs=[project_name4],outputs=[emo_status_text,emo_speaker])
        #emo_del_class_btn.click()
        emo_del_wav_btn.click(
            del_wav_in_class,
            inputs=[emo_speaker,emo_chosen_class,*emo_checkbox_list],
            outputs=[*emo_file_name_list,*emo_tr_list,*emo_audio_list,*emo_checkbox_list,previous_btn,emo_page_index,next_btn]
        )
        emo_reverse_selection_btn.click(
            reverse_selection,
            inputs=[*emo_checkbox_list],
            outputs=[*emo_checkbox_list]
        )
        emo_del_class_btn.click(
            del_rename_class,
            inputs=[emo_speaker,emo_chosen_class],
            outputs=[emo_chosen_class]
        )
        emo_enter_rename_btn.click(
            del_rename_class,
            inputs=[emo_speaker,emo_chosen_class,emo_enter_rename],
            outputs=[emo_chosen_class,emo_enter_rename]
        )        
        next_btn.click(
            switch_next_page,
            inputs=[emo_speaker,emo_chosen_class],
            outputs=[*emo_file_name_list,*emo_tr_list,*emo_audio_list,*emo_checkbox_list,previous_btn,emo_page_index,next_btn]
            )
        previous_btn.click(
            switch_previous_page,
            inputs=[emo_speaker,emo_chosen_class],
            outputs=[*emo_file_name_list,*emo_tr_list,*emo_audio_list,*emo_checkbox_list,previous_btn,emo_page_index,next_btn]
            ) 
        emo_write_btn.click(
            emo_write,
            inputs=[project_name4],
            outputs=[emo_status_text]
        ) 
        ec_gen_btn.click(
            run_ec_gen,
            inputs=[project_name4,ec_gen_n_clu,ec_gen_range],
            outputs=[emo_status_text]
        )      
webbrowser.open(f"http://127.0.0.1:{args.server_port}")
app.launch(share=False,server_port=args.server_port)