Supabase StorageにFastAPIからファイルアップロードする備忘録

supabase and fastapi Python

FastAPIを使ってファイルをStorageサービスにアップロードする方法およびファイルのURLを取得に関する備忘録。

こちらの記事の補足として、Storageサービスを利用することになったので、別記事としてまとめたものです。

音声ファイルをgTTSで作成して、ファイルをSupabase Storageにアップロードする処理になります。

✅ 前提条件

  • Supabase プロジェクト作成済み
  • Supabase Storage に “audio” などのバケット作成済み(パブリック設定)
  • Supabase APIキー(サービスロールキー or anonキー)とURLがある
  • Python バックエンドで supabase を使う

 

Storage bucketの作成

Supabase project内でStorageにアクセスする。

Supabase bucket

 

New bucket からbucketを作成する。

Supabase public bucket

Public bucket にしてbucketを作成する。

任意のファイルをbucketにアップロードする。

GET Bucket file URL

ファイルを選択して Get URL からURLを取得する。

すると、以下のようなURLが得られる。

https://[YOUR_PROJECT].supabase.co/storage/v1/object/public/my-bucket/supabase-logo-dark.png

Project Settings > Storage

S3 Connection には以下のようなEndpointの記載があるが、このパスだと上手くいかなかったので、上記のようなパスを使う。

https://[YOUR_PROJECT].supabase.co/storage/v1/s3

 

🔑 Supabase のキーの種類

種類 用途 安全性
anon 公開キー フロントエンドから読み取りなどの操作(制限付き) 安全に公開可能
service_role サーバーキー フルアクセス権限(読み書き・削除) バックエンドのみで使用!絶対に公開しないこと

✅ SUPABASE_KEY の取得方法

  1. Supabaseの プロジェクトページ にログイン
  2. 対象のプロジェクトを選択
  3. 左メニュー → ⚙️ Project Settings をクリック
  4. API Keys をクリック
  5. 下記のようなキーが表示されます:
    • anon public(→ フロントエンド用)
    • service_role(→ バックエンドでの Supabase Storage 書き込みなどに使う)

API Keys

Project Settings > API Keys

service_role keyの値を表示して、控えておく。

Supabase API Keys

 

音声ファイルをStorageへ保存する

必要なライブラリ

pip install supabase

① gTTS で mp3 を一時ファイルに保存

from gtts import gTTS
import uuid

def generate_audio(text: str, lang: str = "ja") -> str:
    tts = gTTS(text=text, lang=lang)
    filename = f"{uuid.uuid4()}.mp3"
    tts.save(filename)
    return filename

② Supabase にアップロードして公開URLを取得

from supabase import create_client
import os

SUPABASE_URL = "<https://xxxx.supabase.co>"
SUPABASE_KEY = "your-service-role-or-anon-key"
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)

def upload_to_supabase(filepath: str, bucket: str = "audio") -> str:
    filename = os.path.basename(filepath)
    
    if not os.path.exists(filepath):
        raise FileNotFoundError(f"file not found: {filepath}")
    
    with open(filepath, "rb") as f:
        # Upload file to Supabase Storage
        supabase.storage.from_(bucket).upload(filename, f, file_options={"content-type": "audio/mpeg"})
    
    # Generate public URL(bucket needs public access)
    public_url = f"{SUPABASE_URL}/storage/v1/object/public/{bucket}/{filename}"
    return public_url

③ 一連の処理をまとめる関数

def create_audio_and_upload(text: str, lang: str = "ja") -> str:
    mp3_file = generate_audio(text, lang)
    try:
        url = upload_to_supabase(mp3_file)
        return url
    finally:
        os.remove(mp3_file)  # delete from local

✅ 結果:得られるもの

  • ユーザーが話した内容に対するAIの返答をgTTSでmp3に変換
  • mp3をSupabaseの”audio”バケットに保存
  • https://xxxx.supabase.co/storage/v1/object/public/audio/abc123.mp3 のような再生可能なURLを返す

これを POST /tts の中に組み込むだけでOK

@app.post("/tts")
async def tts_api(data: TextInput):
    url = create_audio_and_upload(data.text, lang=data.lang or "ja")
    return {"audio_url": url}