Chiloh

Chiloh Wei

一个尝试理解世界,理解自己的人
jike
twitter

05-現在は雑多ではない

image

カバー写真は 21 年 10 月 06 日に撮影され、私が初めてナイトクラブに入った時のものです。友達とボックス席を頼み、周りは様々な人々で、私はその中で浮いていました。


今週は南昌に出張に行きました。出張のたびに炭水化物と風土人情のもてなしが満載です。私はあまり話さない方で、食事の時は観察者になることが多く、毎回面白い人や興味深い点を発見できます。本当に素晴らしいです~

今週、飛行機の中でこの本をざっと読みました。非常に良い本です。「創意」について語っているように見えますが、実際には多様な道があり、同じ目的に向かっています。私が最も好きなこの一節を共有します:

私たち一人一人の心の奥深くには、個人の創意の泉があるようです。同時に、より広範で個人を超えた、人類全体に属する共通の泉が存在し、そこには様々な原始的で深遠な集団の知恵が蓄えられています。この巨大な泉は私たちの体内にあるかもしれませんし、私たちがそれに通じるパイプを持っているかもしれません。

帰ってから、私は友人のグループに自分の感想を共有しましたが、わずか 3 行の文字だけでした:

image

Vercel も自分の生成的 UI システムを発表したのを見ました。テキストを入力するだけで、シンプルな UI インターフェースを描画できます。以前共有した screenshot-to-code に非常に似ています。

今週、自分のブログの内容をクローリングするためにこのクローラーフレームワークをテストしました。そして、それを訓練中の自分の分身に与えましたが、効果はなかなか良かったです。

感想#

今週の AI に関する実践は、オープンソースプロジェクトに基づいています:tts。提供されたソリューションを利用して、2 分もかからずに cloudflare 上に Azure tts を使用した音声合成のウェブサイトをデプロイしました:音声合成

image

全体のソリューションは非常にシンプルで、cloudflare 上に新しいワーカーを作成し、以下のコードを書くだけで実現できます:

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})


function generateUUID() {
    let uuid = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) {
        let r = Math.random() * 16 | 0,
            v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
    return uuid;
}

const API_URL = "https://southeastasia.api.speech.microsoft.com/accfreetrial/texttospeech/acc/v3.0-beta1/vcg/speak";
const DEFAULT_HEADERS = {
    authority: "southeastasia.api.speech.microsoft.com",
    accept: "*/*",
    "accept-language": "zh-CN,zh;q=0.9",
    customvoiceconnectionid: generateUUID(),
    origin: "https://speech.microsoft.com",
    "sec-ch-ua":
        '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"Windows"',
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site",
    "user-agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
    "content-type": "application/json",
};

const speechApi = async (ssml) => {
    const data = JSON.stringify({
        ssml,
        ttsAudioFormat: "audio-24khz-160kbitrate-mono-mp3",
        offsetInPlainText: 0,
        properties: {
            SpeakTriggerSource: "AccTuningPagePlayButton",
        },
    });

    try {
        const response = await fetch(API_URL, {
            method: "POST",
            responseType: "arraybuffer",
            headers: DEFAULT_HEADERS,
            body: data
        });

        if (!response.ok) {
            throw new Error(`Request failed with status ${response.status}`);
        }

        return response.arrayBuffer();
    } catch (error) {
        console.error("Error during API request:", error);
        throw error;
    }
};

const handleRequest = async (request) => {
    // リクエストURLを解析
    const url = new URL(request.url);

    const clientIP = request.headers.get("CF-Connecting-IP")

    if (url.pathname == "/") {
        const html = await fetch("https://files.chiloh.net/azure-tts.html")

        const page = await html.text()
        return new Response(page, {
            headers: {
                "content-type": "text/html;charset=UTF-8",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": "true",
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Methods": "*",
                "ip": `Access cloudflare's ip:${clientIP}`
            },
        })
    } else if (url.pathname == "/audio") {
        // クエリパラメータを解析
        const params = new URLSearchParams(url.search);
        // クエリパラメータからテキストを取得
        const text = params.get("text");
        // クエリパラメータから速度を取得
        const rate = params.get("rate");
        // クエリパラメータから音高を取得
        const pitch = params.get("pitch");
        // クエリパラメータから音色を取得
        const voice = params.get("voice");
        // クエリパラメータから音色スタイルを取得
        const voiceStyle = params.get("voiceStyle");
        const ssml = `<speak xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="http://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" version="1.0" xml:lang="en-US">
    <voice name="${voice}">
    <mstts:express-as style="${voiceStyle}">
        <prosody rate="${rate}%" pitch="${pitch}%">
        ${text}
       </prosody>
        </mstts:express-as>
    </voice>
    </speak>`;

        const audio = await speechApi(ssml);
        const nowtime = new Date().getTime();
        return new Response(audio, {
            headers: {
                "Content-Type": "audio/mpeg",
                "Content-Disposition": `attachment; filename=${nowtime}.mp3`,
            },
        });
    } else if (url.pathname == "/legado") {
        const origin = url.origin
        const params = new URLSearchParams(url.search);
        // クエリパラメータからテキストを取得
        // const text = params.get("text");
        // クエリパラメータから速度を取得
        const rate = params.get("rate");
        // クエリパラメータから音高を取得
        const pitch = params.get("pitch");
        // クエリパラメータから音色を取得
        const voice = params.get("voice");
        // クエリパラメータから音色スタイルを取得
        const voiceStyle = params.get("voiceStyle");

        const dataJson = {
            "concurrentRate": "",//並行率
            "contentType": "audio/mpeg",
            "header": "",
            "id": Date.now(),
            "lastUpdateTime": Date.now(),
            "loginCheckJs": "",
            "loginUi": "",
            "loginUrl": "",
            "name": `Azure  ${voice} ${voiceStyle} pitch: ${pitch} rate:${rate}`,
            "url": `${origin}/audio?text={{speakText}}&rate=${rate}&pitch=${pitch}&voice=${voice}&voiceStyle=${voiceStyle},{"method":"GET"}`,
        }

        return new Response(JSON.stringify(dataJson), {
            headers: {
                "content-type": "application/json;charset=UTF-8",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": "true",
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Methods": "*",
                "ip": `Access cloudflare's ip:${clientIP}`
            },
        })



    } else if (url.pathname == "/sourcereader") {
        const origin = url.origin
        const params = new URLSearchParams(url.search);
        // クエリパラメータからテキストを取得
        // const text = params.get("text");
        // クエリパラメータから速度を取得
        const rate = params.get("rate");
        // クエリパラメータから音高を取得
        const pitch = params.get("pitch");
        // クエリパラメータから音色を取得
        const voice = params.get("voice");
        // クエリパラメータから音色スタイルを取得
        const voiceStyle = params.get("voiceStyle");

        const dataJson = [{
            "customOrder": 100,
            "id": Date.now(),
            "lastUpdateTime": Date.now(),
            "name": ` ${voice} ${voiceStyle} pitch: ${pitch} rate:${rate}`,
            "url": `${origin}/audio?text={{speakText}}&rate=${rate}&pitch=${pitch}&voice=${voice}&voiceStyle=${voiceStyle},{"method":"GET"}`,
        }]
        return new Response(JSON.stringify(dataJson), {
            headers: {
                "content-type": "application/json;charset=UTF-8",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": "true",
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Methods": "*",
                "ip": `Access cloudflare's ip:${clientIP}`
            },
        })
    }
    else {
        return new Response("page", {
            headers: {
                "content-type": "text/html;charset=UTF-8",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": "true",
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Methods": "*",
                "ip": `Access cloudflare's ip:${clientIP}`
            },
        })
    }

}

ページのスタイルを変更したい場合は、以下の行の URL を変更して、自分が調整したフロントエンドページの URL に変更すれば大丈夫です:

const html = await fetch("https://files.chiloh.net/azure-tts.html")

創造することがますます簡単になっています。良いアイデアがあれば、Just do it !!

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。