3
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?

100MBまでの動画をdiscordに送信できるBOTを作ろう!

Last updated at Posted at 2025-04-01

はじめに

discordってとても便利ですよね。気軽に通話できるし、メッセージも簡単にやり取りできます。筆者自身も毎日使用しており、今では必須ツールの1つになっています。
そんなdiscordですが、8MB以上のファイルが送信できない(Freeプラン) というでかすぎる制約があります。
動画をよく送信する私にしてみれば、動画を送る際にいちいち圧縮してから送信するのはめちゃくちゃ面倒くさいです。そこで、discord BOTを使って簡単に圧縮できればいいな、と思い今回の開発に取り組みました。

概要

指定のwebサイトに動画をアップロードすると、8MB制限を回避してdiscordに投稿してくれるBOTを作成します。サーバの人たちがいつでも使えるように、デプロイもします。

本記事は、discord BOTを立ちあげるところは説明しません。discordのBOTの作り方は以下を参考にしてください。
https://qiita.com/ukwhatn/items/c3abfbbd447f5802afa3

コード

ファイル構成を最初に示しておきます。
image.png
ーーーー

フロントエンド

フロントエンドも少しこだわっているので、「そこは俺にとっては重要じゃないんだよ!!」という方は、簡易版の以下のコードを使用してください。

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>動画アップロード</title>

</head>
<body>
    <h1>タイトルを入力してください</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <input type="text" name="title" placeholder="タイトルを入力" required>
        <h1>動画をアップロードしてください</h1>
        <input type="file" name="file" accept="video/*" required>
        <input type="submit" value="アップロード">
    </form>
</body>
</html>

私のこだわりに付き合ってくれる人は、以下に完成版の説明を書きましたのでこちらもご覧になっていただけると嬉しいです。
(執筆中URL)

バックエンド

次に、バックエンド側の処理を説明します。
処理としては、

① フロントから動画を受け取る
② 受け取った動画をCloudinaryのクラウドストレージに保存
③ 保存した動画のURLを取得
④ URLをdiscordに送信する

これだけです。discordでは、動画リンクを張るとその場で再生できるため、8MBの制限を回避することが出来ます。
処理の内容を順に説明します。

① フロントから動画を受け取る

HTMLにて、ファイルをまずは受け取ります。

<input type="file" name="file" accept="video/*" required>

上のように書くことで、ファイルを受け取り、それに対して "file" という識別子を付けることが出来ます。(name="file" の部分)

以下はサーバ側のコードです。

@app.route('/upload', methods=['POST'])
def upload_file():
    """動画を受け取り、Cloudinary にアップロードし、Discord に送信"""
    if 'file' not in request.files:
        return 'ファイルが見つかりませんでした。', 400
    file = request.files['file']
    if file.filename == '':
        return 'ファイル名が空です。', 400

    title = request.form.get('title', 'Video')
    file_path = f"uploads/{file.filename}"
    file.save(file_path)

    threading.Thread(target=process_and_upload, args=(file_path, title)).start()

    # アップロード後に同じページにリダイレクト
    return redirect(url_for('index'))

先ほど、受け取ったファイルに "file" と名前を付けたので、サーバ側で

file = request.files['file']

として、fileに代入します。そして、uploadsフォルダに保存し、そのパスを process_and_upload 関数に渡します。

② 受け取った動画をCloudinaryのクラウドストレージに保存

def process_and_upload(file_path, title):
   """動画をCloudinaryにアップロードし、そのURLをDiscordに送信する"""
   logger.info(f"Starting upload for file: {file_path} with title: {title}")

   try:
       logger.info("Uploading video to Cloudinary...")
       upload_result = cloudinary.uploader.upload(
           file_path, resource_type='video', eager=[{'width': 800, 'height': 600, 'crop': 'limit'}]
       )
       video_url = upload_result['secure_url']
       logger.info(f"Upload successful. Video URL: {video_url}")

       async def send_to_discord():
           logger.info(f"Sending video URL to Discord channel: {CHANNEL_ID}")
           channel = bot.get_channel(CHANNEL_ID)
           if isinstance(channel, discord.TextChannel):
               await channel.send(f"[{title}]({video_url})")
           else:
               logger.error(f"Invalid channel: {CHANNEL_ID}")

       loop = bot.loop
       loop.create_task(send_to_discord())

       logger.info("Video URL sent to Discord successfully.")
   except Exception as e:
       logger.error(f"Error during video upload and Discord send: {e}")

保存したファイルパスを受け取ったら、Cloudinaryのクラウドストレージに保存します。保存方法はとても簡単で、CloudinaryのAPI取得後、

upload_result = cloudinary.uploader.upload(
            file_path, resource_type='video', eager=[{'width': 800, 'height': 600, 'crop': 'limit'}]
        )

と書くだけです。cloudinary.uploader.upload の引数に、ファイルパス、タイプ、サイズを指定し、戻り値をvideo_result に保存しています。

③ 保存した動画のURLを取得

クラウド上の動画URLは video_result[secure_url] で取得することが出来ます。後は、discordに送信するだけで8MB制限を気にせずに動画を貼ることが出来ます。

④ URLをdiscordに送信する

discordに送信する際には、BOTに「ここのチャンネルに送信してくださいね~」と指定してあげる必要があります。そこで登場するのが、チャンネルIDです。
チャンネルIDの取得方法は以下サイトをご覧ください。
https://qiita.com/ryo_001339/items/10379e7e108a9f797e5e

チャンネルIDを取得したら、以下のように書くことでdiscordの指定Ch.に送信することが出来ます。取得したチャンネルIDは、.env に書いているため、コード上ではCHANNEL_IDで呼び出しています。(良く分からない人は .env で検索)

async def send_to_discord():
    channel = bot.get_channel(CHANNEL_ID)
    if isinstance(channel, discord.TextChannel):
        await channel.send(f"[{title}]({video_url})")
    else:
        logger.error(f"Invalid channel: {CHANNEL_ID}")

これは少し工夫なのですが、URLをそのまま送ると見た目が悪いため、サイトで入力してもらったタイトルを用いて[{title}]({video_url})として送信することで、タイトルにURLを埋め込む?ことが出来ます。

これで完了です。
しかし、現状ではローカルでしか動きません。ファイルを圧縮するたびにBOTを起動しているようでは手間がかかってしまうので、デプロイしていつでも簡単に圧縮できるようにしていきましょう。

最後に

今回開発したdiscord BOT のコードを載せておきます
https://github.com/yonuma28/compress_movie

3
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
3
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?