1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Fast APIで動画ファイルのダウンロードをできるようにする

Posted at

はじめに

こちらの記事は過去に作成した記事に機能を追加してみたものになります

過去の記事に目を通してからみていただくと良いかもしれません

何をしたかったか

元々の機能としてはFast APIで作成したエンドポイントにURLを渡した時に、動画ファイルがダウンロードできるようにするという名目で作成しました

そして、作成できたものとしてはdocker経由でコンテナを立てた後に、ローカル内でファイルをダウンロードして保存するという機能でした

これでは、保存した後に一旦ファイルが保存された場所まで確認しにいかなければいけません

今回の修正では、エンドポイントにリクエストを送った際に実際に動画ファイルが返却される(=保存される)という内容に変更してみたいと思います

やったこと

Fast APIでファイルをレスポンスする際に使用できるものといえば「FileResponse」・「StreamResponse」の2つくらいがあると思います

自分の理解では
FileResponseがファイルの準備が完璧になってからレスポンスを返すもの
StreamResponseが逐次レスポンスを返すもの
というような認識です

フロントと結合する際、ダウンロード中に動作ができなくなるのが個人的に好きではないので「StreamResponse」を使って動画ファイルを返却できるようにしてみました

これまでは以下のようにファイルをただローカルに保存していました

with YoutubeDL(ytdlp_opts) as ydl:
    ydl.download(target_url)

そこから以下のように処理を加えました(importなど省略しているものはあります)

def generate_unique_filename():
    return str(uuid.uuid4()) + ".mp4"


@app.post("/yt_download")
async def download_yt_video(jsonbody: get_yt):
    try:
        filename = generate_unique_filename()
        ytdlp_opts = {
            "format": "best[ext=mp4]",
            "outtmpl": filename 
        }
        
        with YoutubeDL(ytdlp_opts) as ydl:
            ydl.download(target_url)
        
        return StreamingResponse(
            open(filename, "rb"),
            media_type="video/mp4",
            headers={"Content-Disposition": "attachment; filename=video.mp4"}
        )
    except:......
    <省略>

変更点

  • これまでは動画ファイルの名称が「URL先の動画のタイトル.mp4」という形で保存するようにしていました

    • この問題点は、同じ動画を保存しようとした場合にダウンロード処理がされないというところが問題でした
    • なので「uuid.mp4」という形式で動画ファイルを保存できるようにしました
    • (今考えると、ダウンロード処理をスキップできるようにすれば、同じものをダウンロードしたい人がいた時に時間が省略ができたかもしれないとも思います)
  • ytdlp_optsのオプション追加

    • outtmpl
      • 出力先の指定
      • 名前の付け方変えたので、ここを変えないとダメですね
  • return StreamingResponse

    • ここが今回の肝になります
    • 一時的にファイルを保存してその内容をopenで読み込み、StreamingResponseの処理に乗っけるような形にしています

結果

この状態で以下のような形でcurlを実行してみると、実行したディレクトリ内にファイルがダウンロードされるようになりました

curl -vX "POST" "http://localhost:xxxx/yt_download" -d "{\"url\": \"https://www.youtube.com/watch?v=xxxxxxx\"}" -H 'Content-Type: application/json' -o video.mp4

スクリーンショット 2025-03-08 20.06.59.png

おわりに

ということで今回はStreaminResponseを使ってみたというところでした
これができるようになったということは、フロントエンドにこの情報を渡して画面からファイルがダウンロードできるようになるのかなとイメージしております

次回はその内容で記事が書ければと思います

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?