123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- #!usr/bin/env python
- # -*- coding: utf-8 -*-
- # author: kuangdd
- # date: 2020/1/5
- """
- ### audio_cli
- 命令行,播放音频,去除背景噪声,音频格式转换。
- 支持递归处理文件夹内的全部音频。
- #### 命令行
- ##### **说明**
- - 用位置参数来控制。
- - 名称说明
- * inpath:输入音频路径或目录。
- * outpath:输出音频路径或目录,如果为目录,则输出的子目录按照inpath的子目录格式输出。
- * sr:音频采样率,默认16000或自动识别采样率。
- * in_format:输入音频格式,主要用以限制为指定后缀名的文件,如果不设置,则处理目录的全部文件。
- * out_format:输出音频格式,主要用以音频格式转换,设置输出音频的后缀名。
- - 中括号【[]】里面的是可选参数。
- #### **工具**
- - auplay: 播放音频
- ```
- auplay inpath [sr] [in_format]
- ```
- - aunoise: 语音降噪
- ```
- aunoise inpath outpath [in_format]
- ```
- - auformat: 音频格式转换
- ```
- auformat inpath outpath out_format [in_format]
- ```
- """
- from pathlib import Path
- import logging
- logging.basicConfig(level=logging.INFO)
- logger = logging.getLogger(Path(__name__).stem)
- import sys
- from functools import partial
- from multiprocessing import Pool
- from tqdm import tqdm
- from pathlib import Path
- import traceback
- import multiprocessing as mp
- from .audio_io import _sr
- from .audio_player import play_audio
- from .audio_noise_remover import remove_noise_os
- from .audio_editor import convert_format_os
- _n_process = max(1, mp.cpu_count() - 2)
- def play_audio_one(inpath, sr):
- try:
- play_audio(inpath, sr=sr)
- except Exception as e:
- logger.info("PlayAudioFailed: {}".format(inpath))
- traceback.print_exc()
- def play_audio_cli():
- fpath = Path(sys.argv[1])
- if len(sys.argv) >= 3:
- sr = int(sys.argv[2])
- else:
- sr = _sr
- if len(sys.argv) >= 4:
- in_format = sys.argv[3]
- else:
- in_format = None
- if fpath.is_file():
- play_audio_one(fpath, sr=sr)
- elif fpath.is_dir():
- tmp = "**/*" if in_format is None else "**/*.{}".format(in_format)
- for inpath in sorted(fpath.glob(tmp)):
- if not inpath.is_file():
- continue
- try:
- play_audio_one(inpath, sr=sr)
- except Exception as e:
- logger.info("PlayAudioFailed: {}".format(inpath))
- traceback.print_exc()
- else:
- assert fpath.exists()
- def remove_noise_one(x):
- outpath = Path(x["outpath"])
- outpath.parent.mkdir(exist_ok=True, parents=True)
- try:
- out = remove_noise_os(**x)
- except Exception as e:
- inpath = str(x["inpath"])
- logger.info("RemoveNoiseFailed: {}".format(inpath))
- traceback.print_exc()
- out = None
- return out
- def remove_noise_cli():
- inpath = Path(sys.argv[1])
- outpath = Path(sys.argv[2])
- if len(sys.argv) >= 4:
- in_format = sys.argv[3]
- else:
- in_format = None
- if inpath.is_file():
- remove_noise_one(dict(inpath=inpath, outpath=outpath))
- elif inpath.is_dir():
- indir = inpath
- outdir = outpath
- kw_lst = []
- tmp = "**/*" if in_format is None else "**/*.{}".format(in_format)
- for inpath in indir.glob(tmp):
- if not inpath.is_file():
- continue
- parts = inpath.relative_to(indir).parts
- outpath = outdir.joinpath(*parts)
- kw = dict(inpath=str(inpath), outpath=str(outpath))
- kw_lst.append(kw)
- pool_jobs(func=remove_noise_one, n_process=_n_process, kwargs_list=kw_lst, tqdm_desc='remove_noise')
- else:
- assert inpath.exists()
- def convert_format_one(x):
- outpath = Path(x["outpath"])
- outpath.parent.mkdir(exist_ok=True, parents=True)
- try:
- out = convert_format_os(**x)
- except Exception as e:
- inpath = str(x["inpath"])
- logger.info("ConvertFormatFailed: {}".format(inpath))
- traceback.print_exc()
- out = None
- return out
- def convert_format_cli():
- inpath = Path(sys.argv[1])
- outpath = Path(sys.argv[2])
- out_format = sys.argv[3]
- if len(sys.argv) >= 5:
- in_format = sys.argv[4]
- else:
- in_format = None
- if inpath.is_file():
- convert_format_one(dict(inpath=inpath, outpath=outpath, in_format=in_format, out_format=out_format))
- elif inpath.is_dir():
- indir = inpath
- outdir = outpath
- kw_lst = []
- tmp = "**/*" if in_format is None else "**/*.{}".format(in_format)
- for inpath in indir.glob(tmp):
- if not inpath.is_file():
- continue
- parts = inpath.parent.relative_to(indir).parts
- name = "{}.{}".format(inpath.stem, out_format)
- outpath = outdir.joinpath(*parts, name)
- kw = dict(inpath=str(inpath), outpath=str(outpath), in_format=in_format, out_format=out_format)
- kw_lst.append(kw)
- pool_jobs(func=convert_format_one, n_process=_n_process, kwargs_list=kw_lst, tqdm_desc='convert_format')
- else:
- assert inpath.exists()
- def pool_jobs(func, n_process=_n_process, kwargs_list=(), post_func=None, tqdm_desc="job"):
- """
- 多进程执行任务。
- :param func: 第一个参数为变化参数,如果多个参数组合变化,请用:【def _func(x): return func(**x)】的方式处理函数。
- :param n_process:
- :param kwargs_list:
- :param post_func:
- :param tqdm_desc:
- :return:
- """
- if post_func is None:
- post_func = lambda x: x
- _tqdm = lambda x: tqdm(x, desc=tqdm_desc, total=len(kwargs_list), ncols=80, mininterval=1)
- if n_process == 0 or n_process == 1:
- for kw in _tqdm(kwargs_list):
- out = func(kw)
- post_func(out)
- else:
- partial_func = partial(func)
- job = Pool(n_process).imap(partial_func, kwargs_list)
- for out in list(_tqdm(job)):
- post_func(out)
- if __name__ == "__main__":
- print(__file__)
|