CoolFace
Apppublic

codemo/fish-speech-1

sourceHugging Facecc-by-nc-sa-4.0updated 2y agoView on Hugging Face
0likes
post_api.py206 linesDownload Raw Back to tools
1import argparse2import base643import wave4 5import ormsgpack6import pyaudio7import requests8from pydub import AudioSegment9from pydub.playback import play10 11from tools.commons import ServeReferenceAudio, ServeTTSRequest12from tools.file import audio_to_bytes, read_ref_text13 14 15def parse_args():16 17    parser = argparse.ArgumentParser(18        description="Send a WAV file and text to a server and receive synthesized audio."19    )20 21    parser.add_argument(22        "--url",23        "-u",24        type=str,25        default="http://127.0.0.1:8080/v1/tts",26        help="URL of the server",27    )28    parser.add_argument(29        "--text", "-t", type=str, required=True, help="Text to be synthesized"30    )31    parser.add_argument(32        "--reference_id",33        "-id",34        type=str,35        default=None,36        help="ID of the reference model o be used for the speech",37    )38    parser.add_argument(39        "--reference_audio",40        "-ra",41        type=str,42        nargs="+",43        default=None,44        help="Path to the WAV file",45    )46    parser.add_argument(47        "--reference_text",48        "-rt",49        type=str,50        nargs="+",51        default=None,52        help="Reference text for voice synthesis",53    )54    parser.add_argument(55        "--output",56        "-o",57        type=str,58        default="generated_audio",59        help="Output audio file name",60    )61    parser.add_argument(62        "--play",63        type=bool,64        default=True,65        help="Whether to play audio after receiving data",66    )67    parser.add_argument("--normalize", type=bool, default=True)68    parser.add_argument(69        "--format", type=str, choices=["wav", "mp3", "flac"], default="wav"70    )71    parser.add_argument("--mp3_bitrate", type=int, default=64)72    parser.add_argument("--opus_bitrate", type=int, default=-1000)73    parser.add_argument("--latency", type=str, default="normal", help="延迟选项")74    parser.add_argument(75        "--max_new_tokens",76        type=int,77        default=1024,78        help="Maximum new tokens to generate",79    )80    parser.add_argument(81        "--chunk_length", type=int, default=100, help="Chunk length for synthesis"82    )83    parser.add_argument(84        "--top_p", type=float, default=0.7, help="Top-p sampling for synthesis"85    )86    parser.add_argument(87        "--repetition_penalty",88        type=float,89        default=1.2,90        help="Repetition penalty for synthesis",91    )92    parser.add_argument(93        "--temperature", type=float, default=0.7, help="Temperature for sampling"94    )95    parser.add_argument(96        "--speaker", type=str, default=None, help="Speaker ID for voice synthesis"97    )98    parser.add_argument("--emotion", type=str, default=None, help="Speaker's Emotion")99    parser.add_argument(100        "--streaming", type=bool, default=False, help="Enable streaming response"101    )102    parser.add_argument(103        "--channels", type=int, default=1, help="Number of audio channels"104    )105    parser.add_argument("--rate", type=int, default=44100, help="Sample rate for audio")106 107    return parser.parse_args()108 109 110if __name__ == "__main__":111 112    args = parse_args()113 114    idstr: str | None = args.reference_id115    # priority: ref_id > [{text, audio},...]116    if idstr is None:117        ref_audios = args.reference_audio118        ref_texts = args.reference_text119        if ref_audios is None:120            byte_audios = []121        else:122            byte_audios = [audio_to_bytes(ref_audio) for ref_audio in ref_audios]123        if ref_texts is None:124            ref_texts = []125        else:126            ref_texts = [read_ref_text(ref_text) for ref_text in ref_texts]127    else:128        byte_audios = []129        ref_texts = []130        pass  # in api.py131 132    data = {133        "text": args.text,134        "references": [135            ServeReferenceAudio(audio=ref_audio, text=ref_text)136            for ref_text, ref_audio in zip(ref_texts, byte_audios)137        ],138        "reference_id": idstr,139        "normalize": args.normalize,140        "format": args.format,141        "mp3_bitrate": args.mp3_bitrate,142        "opus_bitrate": args.opus_bitrate,143        "max_new_tokens": args.max_new_tokens,144        "chunk_length": args.chunk_length,145        "top_p": args.top_p,146        "repetition_penalty": args.repetition_penalty,147        "temperature": args.temperature,148        "speaker": args.speaker,149        "emotion": args.emotion,150        "streaming": args.streaming,151    }152 153    pydantic_data = ServeTTSRequest(**data)154 155    response = requests.post(156        args.url,157        data=ormsgpack.packb(pydantic_data, option=ormsgpack.OPT_SERIALIZE_PYDANTIC),158        stream=args.streaming,159        headers={160            "authorization": "Bearer YOUR_API_KEY",161            "content-type": "application/msgpack",162        },163    )164 165    if response.status_code == 200:166        if args.streaming:167            p = pyaudio.PyAudio()168            audio_format = pyaudio.paInt16  # Assuming 16-bit PCM format169            stream = p.open(170                format=audio_format, channels=args.channels, rate=args.rate, output=True171            )172 173            wf = wave.open(f"{args.output}.wav", "wb")174            wf.setnchannels(args.channels)175            wf.setsampwidth(p.get_sample_size(audio_format))176            wf.setframerate(args.rate)177 178            stream_stopped_flag = False179 180            try:181                for chunk in response.iter_content(chunk_size=1024):182                    if chunk:183                        stream.write(chunk)184                        wf.writeframesraw(chunk)185                    else:186                        if not stream_stopped_flag:187                            stream.stop_stream()188                            stream_stopped_flag = True189            finally:190                stream.close()191                p.terminate()192                wf.close()193        else:194            audio_content = response.content195            audio_path = f"{args.output}.{args.format}"196            with open(audio_path, "wb") as audio_file:197                audio_file.write(audio_content)198 199            audio = AudioSegment.from_file(audio_path, format=args.format)200            if args.play:201                play(audio)202            print(f"Audio has been saved to '{audio_path}'.")203    else:204        print(f"Request failed with status code {response.status_code}")205        print(response.json())206