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

【CI/CD】PRの解説動画をGitHub Actionsで自動生成して、ドキュメント作成の精神的負荷をゼロにする

Posted at

IMG_0419_副本.jpg

2026年になり、Claude Codeや各種AI Agentのおかげで、コーディングの速度は劇的に上がりました。しかし、**「書いたコードを他人に説明するコスト」**は、依然として高いままだと感じていませんか?

Qiitaのトレンドでも「設計の甘さによるAIの手戻り」や「エンジニアの燃え尽き」が話題になっていますが、私たちが最も時間を奪われているのは、実は**「コンテキストの共有」**です。

テキストで長々とPR(Pull Request)の説明を書くのは辛い。でも、Zoomで画面共有して説明するのも時間が合わない。

そこで今回は、**「PRの概要欄(Markdown)から、解説動画を全自動で生成してコメントするWorkflow」**を構築してみました。

これを使えば、ドキュメント作成の時間を節約し、よりクリエイティブな設計業務に集中できるようになります。
アーキテクチャ

今回は以下の構成で実装します。

Trigger: GitHubでPRが作成/更新される。

Action: GitHub ActionsがPRの body(説明文)を取得。

Generate: 外部API (Textideo API) を叩き、テキスト/コードを解説動画に変換。

Feedback: 生成された動画URLをbotがPRにコメントする。

動画生成エンジンには、API経由でMarkdownやコード片をレンダリングできる Textideo を採用しました。FFmpegを自前で組むより圧倒的に早く、かつ保守性が高いからです。
実装(Pythonスクリプト)

まずは、APIを叩くためのスクリプト generate_video.py を作成します。
モダンなPython開発に合わせ、pydantic による型定義と aiohttp による非同期処理を取り入れています。

  1. 依存ライブラリ
    code Txt:requirements.txt

aiohttp==3.9.5
pydantic==2.8.0

  1. コアロジック
    code Python:scripts/generate_video.py

import os
import asyncio
import aiohttp
from pydantic import BaseModel, Field
from typing import Optional
IMG_0421_副本.jpg

APIのエンドポイント設定(Textideoを使用)

API_BASE_URL = "https://textideo.com/"

class VideoRequest(BaseModel):
"""リクエストボディの定義"""
script_text: str = Field(..., description="動画化したいテキストまたはMarkdown")
style: str = Field("tech-dark", description="エンジニア向けのダークモードスタイル")
voice_id: str = "en_dev_v2" # 技術用語に強い音声モデルを指定

class TextideoClient:
def init(self, api_key: str):
self.api_key = api_key
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}

async def generate(self, text: str) -> str:
    """
    テキストを送信し、生成完了までポーリングして動画URLを返す
    """
    payload = VideoRequest(script_text=text)
    
    async with aiohttp.ClientSession() as session:
        # 1. 生成タスクの登録
        print(f"🚀 Sending request to Textideo API...")
        async with session.post(
            f"{API_BASE_URL}/videos/generate", 
            json=payload.model_dump(), 
            headers=self.headers
        ) as resp:
            if resp.status != 200:
                error_text = await resp.text()
                raise Exception(f"API Error: {error_text}")
            
            data = await resp.json()
            task_id = data.get('task_id')
            print(f"⏳ Task started ID: {task_id}")

        # 2. 生成完了まで待機 (ポーリング)
        # 実際の実装ではWebhook推奨ですが、簡易化のためポーリングしています
        for _ in range(20): # 最大約2分待機
            await asyncio.sleep(5)
            async with session.get(
                f"{API_BASE_URL}/tasks/{task_id}",
                headers=self.headers
            ) as status_resp:
                status_data = await status_resp.json()
                status = status_data.get('status')
                
                if status == 'completed':
                    return status_data.get('video_url')
                elif status == 'failed':
                    raise Exception("Video generation failed on server side.")
        
        raise TimeoutError("Video generation timed out.")

async def main():
# GitHub Actionsの環境変数から情報を取得
pr_body = os.getenv("PR_BODY", "No description provided.")
api_key = os.getenv("TEXTIDEO_API_KEY")

if not api_key:
    print("❌ Error: TEXTIDEO_API_KEY is missing.")
    return

# コードブロックなどを含んだ長いテキストを整形
prompt = f"以下のPull Requestの変更点について、技術的な要約動画を作成してください:\n\n{pr_body}"

client = TextideoClient(api_key)
try:
    video_url = await client.generate(prompt)
    print(f"✅ Video Generated: {video_url}")
    
    # GitHub ActionsのOutputに値をセット
    with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
        print(f"video_url={video_url}", file=fh)
        
except Exception as e:
    print(f"❌ Error: {e}")
    exit(1)

if name == "main":
asyncio.run(main())

GitHub Actionsの設定

次に、PRが作られたときにこのスクリプトを動かすWorkflow定義です。
code Yaml:.github/workflows/pr-video-explainer.yml

name: PR Video Explainer

on:
pull_request:
types: [opened, edited]

jobs:
generate-video:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # コメント投稿のために必要

steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Set up Python
    uses: actions/setup-python@v5
    with:
      python-version: '3.12'

  - name: Install dependencies
    run: |
      pip install aiohttp pydantic

  - name: Generate Video from PR Body
    id: video_gen
    env:
      TEXTIDEO_API_KEY: ${{ secrets.TEXTIDEO_API_KEY }}
      PR_BODY: ${{ github.event.pull_request.body }}
    run: python scripts/generate_video.py

  - name: Comment on PR
    uses: actions/github-script@v7
    with:
      script: |
        const videoUrl = "${{ steps.video_gen.outputs.video_url }}";
        const msg = `🤖 **AI解説動画が生成されました**\n\nこのPRの変更内容を要約した動画です。レビューの参考にしてください。\n\n[![Video](${videoUrl})](${videoUrl})`;
        
        github.rest.issues.createComment({
          issue_number: context.issue.number,
          owner: context.repo.owner,
          repo: context.repo.repo,
          body: msg
        })

実際の効果

このWorkflowを導入してから、以下のような変化がありました。

レビュワーの負担減: コードを読む前に1分の動画を見ることで、全体像(Context)が一瞬で掴めるようになった。

非エンジニアへの共有: PMやデザイナーに仕様変更を伝える際、動画URLを投げるだけで済むようになった。

ドキュメント作成の時短: 以前はScreenshotsを貼って説明文を書いていましたが、今は「とりあえずコードをpushすれば動画ができる」という安心感があります。

まとめ

AI時代において、コードを書く速度は上がりましたが、それを「伝える」速度も同じように上げる必要があります。
もし、ドキュメント作成やPRの説明文記述に疲弊している方がいれば、このような**「説明の自動化」**アプローチを試してみてください。
微信图片_20260113095311_1025.png

今回使用したAPIは ai video generator
で取得できます。開発者向けのドキュメントも充実しており、今回のようなCI連携もスムーズに実装できました。

ぜひ、皆さんの「開発DX」向上の参考に慣れば幸いです。

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