蜜桃av色欲a片精品一区,麻豆aⅴ精品无码一区二区,亚洲人成网站在线播放影院在线,亚洲 素人 字幕 在线 最新

微立頂科技

新聞資訊

創(chuàng)新 服務(wù) 價(jià)值

  虛擬女友初步調(diào)研總結(jié)2024-0212(轉(zhuǎn)載)

發(fā)布日期:2024/2/19 18:58:15      瀏覽量:

虛擬女友初步調(diào)研總結(jié)2024-0212(轉(zhuǎn)載)


轉(zhuǎn)自:https://zhuanlan.zhihu.com/p/682012849


整個(gè)AI生成領(lǐng)域的變化,已經(jīng)非??植懒?,呈現(xiàn)出一副勃勃生機(jī),萬(wàn)物競(jìng)發(fā)的狀態(tài)。

  • 文本生成和對(duì)話領(lǐng)域,有Gemini-PRO,GPT4為代表的大語(yǔ)言模型,相當(dāng)于有了大腦;
  • 語(yǔ)音識(shí)別領(lǐng)域,有openai的whisper、阿里的funasr為代表的(Speech Recontion)語(yǔ)音識(shí)別模型,有了聽覺。
  • 視覺識(shí)別這塊,有Gemini-PRO的免費(fèi)api可以白嫖,可以直接處理文本+圖片信息,可以說(shuō)是 開天眼了。
  • 再然后就是前段時(shí)間看到花兒不哭大佬的新作品:GPT-sovits,這東西可以只用一分鐘的音頻,做few-shot訓(xùn)練,然后就能直接拿到參考音頻的音色,毫不夸張的說(shuō),只需要一分鐘的錄音,就能偷掉別人的嗓子!霍金來(lái)了都得點(diǎn)贊。
  • 最后是數(shù)字人視頻生成,這個(gè)對(duì)我來(lái)說(shuō)是一個(gè)全新的領(lǐng)域,我也只是淺嘗了一下,快速做一個(gè)記錄,和大家一起學(xué)習(xí)。我主要使用的是Linly-Talker。
  • demo視頻:【賽博鷹醬給您拜年了】 賽博鷹醬給您拜年了_嗶哩嗶哩_bilibili

趁著過(guò)年這段時(shí)間比較浮躁,快速體驗(yàn)了一下這個(gè)功能,希望為后面的智能小車,以及最終的虛擬女友,做一個(gè)技術(shù)鋪墊。

由于文本生成和視覺識(shí)別都是調(diào)用api,所以接下來(lái)主要介紹語(yǔ)音識(shí)別、聲音復(fù)刻和數(shù)字人生成這三個(gè)部分。

1. 語(yǔ)音識(shí)別:whisper or FunASR?


openai的whisper

后面使用的是openai 開源的whisper,網(wǎng)上大家都說(shuō)它是最強(qiáng)語(yǔ)音識(shí)別模型。whisper有三種調(diào)用方式,做一下總結(jié):

  1. api調(diào)用:對(duì)于臨時(shí)使用、長(zhǎng)文本、不用即時(shí)對(duì)話的場(chǎng)景,用免費(fèi)的3.5api,就可以直接調(diào)用,國(guó)內(nèi)延遲比較高,差不多得3-18秒,才能完成一次識(shí)別,非常不穩(wěn)定,不適合實(shí)時(shí)對(duì)話。另外中文識(shí)別效果一言難盡,得字正腔圓的普通話才行,甚至于有時(shí)候還會(huì)生成繁體字。不知道氪金用戶,或者用azure的api會(huì)不會(huì)好些。
  2. 官網(wǎng)開源的whisper:官網(wǎng)的whisper本地部署,這個(gè)要求你得有至少8Gb的顯存,我自己用的4060顯卡,勉強(qiáng)可以用medium,推理速度比較穩(wěn)定,大概是2秒左右,識(shí)別2秒的音頻。缺點(diǎn)是一樣的,中文識(shí)別效果不是很好,錯(cuò)字、標(biāo)點(diǎn)亂打、繁體。
  3. fast-whisper:這個(gè)項(xiàng)目我得貼一下鏈接:github.com/SYSTRAN/fast, 它大大降低了對(duì)顯存的要求!

另外,需要提一句的是,large-v2的識(shí)別效果一般會(huì)比v3更好,所以如果大家要是用whisper的格式,推薦使用fast-whisper:large-v2。

1.1 關(guān)于語(yǔ)音識(shí)別的自動(dòng)分段:

在連續(xù)對(duì)話的邏輯中,不得不提的是一個(gè)技術(shù)是"語(yǔ)音活性檢測(cè) (Voice activity detection,VAD)",即當(dāng)一個(gè)正在錄音的循環(huán)中,怎么判斷有人聲,怎么判斷,這段話說(shuō)完了,開始進(jìn)入對(duì)話的邏輯?

好消息是fast whisper倉(cāng)庫(kù)自帶vad檢測(cè)模塊,因此,只需要做一個(gè)集成封裝就好。我的主要工作集中在:

  1. 采集音頻信號(hào)
  2. 判斷是否有人聲,調(diào)用vad模塊,可以直接實(shí)時(shí)判斷當(dāng)前音頻是否有人聲。
  3. 判斷是否是一個(gè)完整的對(duì)話,這里的思路比較抽象
  1. 提取完整輸入音頻之后,保存到本地,然后調(diào)用本地的whisper模型,進(jìn)行語(yǔ)音識(shí)別,獲取文本;
  2. 將文本+Prompt,輸入給GPT3.5,拿到對(duì)話文本;
  3. 將對(duì)話文本輸入給GPT3.5的tts模塊,拿到回答音頻文件;
  4. 播放回復(fù)音頻。

這里貼一下我的調(diào)用示例代碼,也算是開源了,如果有幫助,懇請(qǐng)幫忙給帖子點(diǎn)個(gè)贊吧:




# 需要在fast-whipsper工作目錄中運(yùn)行。

import pyaudio
import wave
import time
import tenacity
import openai
import random
import re
from openai import OpenAI
import openai
import numpy as np
from faster_whisper import WhisperModel
import pyaudio  # 導(dǎo)入PyAudio庫(kù),用于音頻錄制和播放
import pygame
from faster_whisper.vad import get_vad_model
chatpaper_keys = """
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
    """
chatpaper_keys = chatpaper_keys.strip()
chatpaper_keys_list = re.findall(r’sk-\w+’, chatpaper_keys)


def play_mp3(file_path):
    pygame.mixer.init()
    pygame.mixer.music.load(file_path)
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():  # Wait for music to finish playing
        pygame.time.Clock().tick(10)
    # 停止混音器
    pygame.mixer.music.stop()
    # 卸載當(dāng)前加載的音樂(lè)流,釋放資源
    pygame.mixer.music.unload()
    # 退出混音器
    pygame.mixer.quit()

def get_tts(client, input_text, output_path="output.mp3"):
    response = client.audio.speech.create(
    model="tts-1",
    voice="nova",
    input=input_text,
    )
    st = time.time()
    response.stream_to_file(output_path)
    print("save audio time:", time.time()-st)

@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, min=4, max=10),
                stop=tenacity.stop_after_attempt(8),
                reraise=True)
def get_response(client, robot_state=’’, user_task=’’):
    openai.api_key = random.choice(chatpaper_keys_list)
    st = time.time()
    # 限制info和prompts的長(zhǎng)度
    robot_state = robot_state[:400]
    user_task = str(user_task)[:600]

    messages = [
        {"role": "system", "content": "你是一個(gè)對(duì)話機(jī)器人,你需要根據(jù)用戶的問(wèn)題回答."},
        {"role": "assistant", "content": ""},
        {"role": "user", "content": f"""
            根據(jù)用戶的命令,簡(jiǎn)潔回答問(wèn)題。
            robot_state: {robot_state},
            user_task: {user_task}.        
            output format:
            你好主人:xxx(具體回復(fù)).
            """},
    ]

    api = "gpt-3.5-turbo"
    response = client.chat.completions.create(
        model=api,
        messages=messages,
        temperature=0.0,
    )
    result = ’’
    for choice in response.choices:
        result += choice.message.content
    return result


class VoiceRecorder:
    def __init__(self, audio_path=’mic_output.wav’):
        # 音頻參數(shù)
        self.format = pyaudio.paInt16
        self.channels = 1
        self.audio = pyaudio.PyAudio()
        self.frames = []
        self.audio_path = audio_path
        # Run on GPU with FP16
        model_size = "large-v2"
        
        self.model = WhisperModel(model_size, device="cuda", compute_type="float16")
        self.history = []

    def start_recording(self):
        # 打開錄音流
        self.stream = self.audio.open(format=self.format, channels=self.channels,
                                      rate=self.rate, input=True,
                                      frames_per_buffer=self.chunk)
        self.frames = []
        print("Recording...")

    def stop_recording(self):
        # 停止錄音
        self.stream.stop_stream()
        self.stream.close()
        print("Finished recording.")      

    def play_txt(self,):  
        OPENAI_API_KEY = np.random.choice(chatpaper_keys_list)
        client = OpenAI(api_key=OPENAI_API_KEY)

        # 語(yǔ)音識(shí)別:
        st = time.time()
        segments, info = self.model.transcribe(self.audio_path, beam_size=5,
                                               initial_prompt="你是一個(gè)對(duì)話機(jī)器人,你需要根據(jù)用戶的問(wèn)題,回答對(duì)應(yīng)的問(wèn)題.",)

        print("Detected language ’%s’ with probability %f" % (info.language, info.language_probability))

        for segment in segments:
            print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, segment.text))

        print("time:", time.time()-st)

        st = time.time()
        robot_state = ’默認(rèn)狀態(tài)’
        user_task = segment.text
        robot_response = get_response(client, robot_state, user_task)
        print("robot_response: ", robot_response)
        print("robot_response Time taken: ", time.time() - st)

        # 語(yǔ)音合成
        st = time.time()
        output_path = ’output.mp3’
        get_tts(client, robot_response, output_path=output_path)

        print("get_tts Time taken: ", time.time() - st)
        

        # 播放MP3文件
        st = time.time()
        play_mp3(output_path)
        print("Time taken: ", time.time() - st)

    def save_recording(self, file_name):
        # 保存錄音到文件
        wave_file = wave.open(file_name, ’wb’)
        wave_file.setnchannels(self.channels)
        wave_file.setsampwidth(self.audio.get_sample_size(self.format))
        wave_file.setframerate(self.rate)
        wave_file.writeframes(b’’.join(self.frames))
        wave_file.close()
        print(f"Recording saved as {file_name}")

    def find_indices(self, speech_list, time_num=2):
        # 初始化索引
        first_index = None
        last_index = None
        lst = [0 if sp < 0.5 else 1 for sp in speech_list]
        # 遍歷列表,找到第一個(gè)0到1的索引
        for i in range(len(lst) - 1):
            if lst[i] == 0 and lst[i + 1] == 1:
                first_index = i + 1
                break
        
        # 如果沒有找到0到1的轉(zhuǎn)變,返回None
        if first_index is None:
            return None

        # 從找到的第一個(gè)1開始,遍歷列表,找到符合條件的最后一個(gè)1到0的轉(zhuǎn)變
        for i in range(first_index, len(lst) - 1):
            if lst[i] == 1 and lst[i + 1] == 0:
                # 檢查是否有至少time_num個(gè)連續(xù)的0
                zero_count = 0
                for j in range(i + 1, len(lst)):
                    if lst[j] == 0:
                        zero_count += 1
                    else:
                        break
                if zero_count >= time_num:
                    last_index = i
                    break # 可以提前結(jié)束循環(huán),因?yàn)槲覀冎恍枰詈笠粋€(gè)符合條件的索引

        # 如果沒有找到符合條件的1到0的轉(zhuǎn)變,或者只有0沒有1,返回None
        if last_index is None:
            return None

        # 返回第一個(gè)0到1的索引和最后一個(gè)符合條件的1到0的索引
        return (first_index, last_index)
                
    def run(self):
        # 開始運(yùn)行錄音程序
        
        temp  = []
        self.audio_rate = 16000
        self.rate = 16000
        self.chunk = 1024
        self.stream = self.audio.open(format=self.format, channels=self.channels,
                                      rate=self.rate, input=True,
                                      frames_per_buffer=self.chunk)
        self.vad_model = get_vad_model()
        self.vad_state = self.vad_model.get_initial_state(batch_size=1)
        self.frames = []
        self.speech_list = []
        time_sum = 0
        time_count = 0
        time_th = 1.0
        print("Recording...")
        while True:
            # 進(jìn)入無(wú)限錄音模式:
            st = time.time()            
            # 獲取當(dāng)前幀的數(shù)據(jù),chunk=1024
            data = self.stream.read(self.chunk)            
            audio_int16 = np.frombuffer(data, np.int16)
            audio_float32 = np.array(audio_int16).astype(np.float32)/32768.0  #(num_samples,)
            # 利用vad檢測(cè)是否有人聲的概率
            speech_prob, self.vad_state = self.vad_model(audio_float32, self.vad_state, self.audio_rate)
            temp.append(audio_float32)
            # 判斷當(dāng)前幀是否有人聲
            is_speech = speech_prob[0][0] > 0.5
            # 把所有的數(shù)據(jù)和人聲判斷都存到列表中。
            self.frames.append(data)
            self.speech_list.append(is_speech)            

            time_sum += time.time() - st
            time_count += 1
            time_mean = time_sum / time_count
            time_num = time_th/(time_mean+0.0001)
            # 根據(jù)人聲判斷來(lái)送篩選是否有人聲,且人聲的索引。
            res = self.find_indices(self.speech_list, time_num=time_num)
            if res is not None:
                self.frames = self.frames[res[0]:res[1]]
                file_name = self.audio_path
                # 將人聲對(duì)應(yīng)的數(shù)據(jù)存到本地
                self.save_recording(file_name)
                # 和gpt對(duì)話,并且調(diào)用tts,最后播放
                self.play_txt()
                self.frames = []
                self.speech_list = []
        # 清理工作
        self.audio.terminate()

print("Press and hold space to record, release to stop and save the audio. Press Esc to exit.")
recorder = VoiceRecorder()
recorder.run()



阿里的Funasr:

中間寫了一個(gè)插曲,繼續(xù)介紹第二個(gè)語(yǔ)音識(shí)別方案:阿里的funasr。

不得不說(shuō),我當(dāng)初小瞧了它。但現(xiàn)在使用下來(lái),funasr的優(yōu)勢(shì)還是很明顯的:部署簡(jiǎn)單,模型小,推理速度快,對(duì)顯存要求低。

最最關(guān)鍵的是,它對(duì)中文更友好!除非是方言和特殊的術(shù)語(yǔ),基本上都能識(shí)別出來(lái)。

另外,它應(yīng)該還是可以和阿里自家的emotion2vec結(jié)合起來(lái),用于音頻的情感識(shí)別,對(duì)后面的聲音復(fù)刻很有用。

OK,但funasr的使用我就不多介紹了,大家直接看后面的內(nèi)容就好了。(這個(gè)帖子今天晚上要寫完,明天不能碰這塊了,所以越寫越急躁~)

聲音復(fù)刻-gpt-sovits:

音色復(fù)刻,我的了解一樣很少,印象中只是看過(guò)“AI孫燕姿”和“郭德綱說(shuō)英文相聲”,知道AI現(xiàn)在能做到比較恐怖的程度。但我看完花佬的新項(xiàng)目之后,才被深刻的震撼到,原來(lái)只需要花一兩個(gè)小時(shí)的配置,加一分鐘的錄音,就能把別人的嗓子復(fù)刻出來(lái),簡(jiǎn)直是太恐怖了。

我不知道之前的什么bert-sovits,甚至也不知道GPT-sovits的技術(shù)原理,我只是最簡(jiǎn)單的使用整合包,跑數(shù)據(jù)、微調(diào)模型+推理整活。

我之前玩的時(shí)候,官方倉(cāng)庫(kù)還有不少bug,現(xiàn)在大家閉眼沖官方倉(cāng)庫(kù)的整合包就行,

If you are a Windows user (tested with win>=10) you can install directly via the prezip. Just download the prezip, unzip it and double-click go-webui.bat to start GPT-SoVITS-WebUI.

點(diǎn)擊prezip下載就好了,文件比較大,需要點(diǎn)魔法+好的網(wǎng)速。最好是谷歌瀏覽器下載,這樣比較穩(wěn)定。


數(shù)字人倉(cāng)庫(kù):Linly-Talker

GitHub - Kedreamix/Linly-Talker

大家自己玩就好,我不介紹了,沒時(shí)間了。

現(xiàn)在最大的問(wèn)題是口型和眼神不太對(duì)。

數(shù)字人進(jìn)階方案:ER-NeRF和geneface++

參考視頻:【AI 數(shù)字人制作(方案六)-嗶哩嗶哩】 b23.tv/vOk1IMg

點(diǎn)評(píng):這兩個(gè)是目前比較完善的開源方案,都是需要對(duì)特定個(gè)人微調(diào),但好像存在長(zhǎng)發(fā)亂飄的問(wèn)題。

另外還有一個(gè)wav2lip的方案,值得探索。



  業(yè)務(wù)實(shí)施流程

需求調(diào)研 →

團(tuán)隊(duì)組建和動(dòng)員 →

數(shù)據(jù)初始化 →

調(diào)試完善 →

解決方案和選型 →

硬件網(wǎng)絡(luò)部署 →

系統(tǒng)部署試運(yùn)行 →

系統(tǒng)正式上線 →

合作協(xié)議

系統(tǒng)開發(fā)/整合

制作文檔和員工培訓(xùn)

售后服務(wù)

馬上咨詢: 如果您有業(yè)務(wù)方面的問(wèn)題或者需求,歡迎您咨詢!我們帶來(lái)的不僅僅是技術(shù),還有行業(yè)經(jīng)驗(yàn)積累。
QQ: 39764417/308460098     Phone: 13 9800 1 9844 / 135 6887 9550     聯(lián)系人:石先生/雷先生