Databricksでgpt-4o-mini-ttsモデルを動かしてみる

こちらのCookbookが更新されてました。

https://cookbook.openai.com/examples/gpt_with_vision_for_video_understanding

以前試した際には、生成されたテキストをTTS APIに渡して音声にしてもらってました。

https://qiita.com/taka_yayoi/items/f0fd89e2c93808423102

[GPT-4o mini TTS](https://platform.openai.com/docs/models/gpt-4o-mini-tts)モデルが公開されたことで、モデルを呼び出すことでテキストから音声を生成できます。

こちらの動画を使います。前回同様うちのインコたちです。

https://vimeo.com/1083091946

```py
%pip install opencv-python
%pip install -U openai
%pip install -U mlflow
%restart_python
```

```py
import mlflow
mlflow.openai.autolog()
```

```py
from IPython.display import display, Image, Audio

import cv2  # ビデオを読み取るためにOpenCVを使用しています。インストールするには !pip install opencv-python
import base64
import time
from openai import OpenAI
import os
import requests

client = OpenAI(api_key=dbutils.secrets.get("demo-token-takaaki.yayoi", "openai_api_key"))

os.environ['OPENAI_API_KEY'] = dbutils.secrets.get("demo-token-takaaki.yayoi", "openai_api_key")
```

```py
video = cv2.VideoCapture("birds.MOV")

base64Frames = []
while video.isOpened():
    success, frame = video.read()
    if not success:
        break
    _, buffer = cv2.imencode(".jpg", frame)
    base64Frames.append(base64.b64encode(buffer).decode("utf-8"))

video.release()
print(len(base64Frames), "frames read.")
```

```py
result = client.responses.create(
    model="gpt-4.1-mini",
    input=[
        {
            "role": "user",
            "content": [
                {
                    "type": "input_text",
                    "text": (
                        "これらはビデオのフレームです。デイビッド・アッテンボローのスタイルで短いナレーションスクリプトを作成してください。ナレーションのみを含めてください。"
                    )
                },
                *[
                    {
                        "type": "input_image",
                        "image_url": f"data:image/jpeg;base64,{frame}"
                    }
                    for frame in base64Frames[0::25]
                ]
            ]
        }
    ]
)

print(result.output_text)
```

> ほら見てください。この小さな森の住人たちは、身近な資源を巧みに利用しています。ビンディッドパロットの鮮やかな色彩と繊細なくちばしが、紙袋の秘密の中に隠された宝物を探り出すのです。自然の知恵と遊び心を持つ彼らの、日常の小さな冒険。こんな瞬間こそ、生命の不思議を教えてくれます。

ここからが前回と違います。TTS APIではなく`gpt-4o-mini-tts`モデルを呼び出します。

```py
instructions = """
声の影響: 穏やかで落ち着いた、温かみのある魅力的な声で、自然界への畏敬の念と静かな敬意を伝える。

トーン: 好奇心旺盛で洞察力に富み、穏やかな驚きと深い尊敬の念を持って話す。

ペース: 均等で安定したペースで、新しい種や予期しない行動を紹介する際にはリズムにわずかな上昇を持たせる。視覚を吸収するための自然な間を取る。

感情: 控えめな感情を込め、好奇心、共感、賞賛を含みつつも、感傷的や過度に劇的にならないようにする。

強調: 科学的および記述的な言語（「繊細な翼が日光に輝く」、「見えない生命の交響曲」、「樹冠の下で繰り広げられる古代の儀式」）を強調し、イメージと理解を豊かにする。

発音: 明瞭で明確な発音、わずかに丸みを帯びた母音で、アクセスしやすく権威あるものにする。

間: 重要な事実や転換を紹介する前に思慮深い間を挿入する（「そして... 突然のざわめきと共に...」）、期待と反省のための空間を作る。
"""

audio_response = response = client.audio.speech.create(
  model="gpt-4o-mini-tts",
  voice="echo",
  instructions=instructions,
  input=result.output_text,
  response_format="wav"
)

audio_bytes = audio_response.content
Audio(data=audio_bytes)
```

プレーヤーで音声を確認できます。Qiitaでは音声埋め込めないので、次のステップで画像に被せます。

音声ファイルとして保存して、ローカルにダウンロードします。

```py
with open('birds_narration.wav', 'wb') as f:
  f.write(audio_bytes)
```

iMovieなどで音声を動画に被せます。

![Screenshot 2025-05-10 at 16.12.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/efa68d51-74fd-4731-a15b-e283bb9fdaa3.png)

出来上がったのがこちら。尺を揃えるのが結構大変です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/eOLbejSb--E?si=2h10aZosIu_c6hFe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)