[Amazon Bedrock] Claude で工場の作業動画から工程分析レポートを自動生成してみました

[Amazon Bedrock] Claude で工場の作業動画から工程分析レポートを自動生成してみました

工場の作業動画から自動で作業分析レポートを生成する仕組みを作ってみました。Amazon Bedrock の Claude に動画フレームを渡すことで、作業要素の分解・サイクルタイム・問題点・改善提案を一度に出力できます。S3・Lambda・Bedrock だけのシンプル構成で、CDK デプロイにも対応しました。
2026.07.15

1 はじめに

製造ビジネステクノロジー部の平内(SIN)です。

工場の現場改善では、作業者の動きの分析が大事な要素になります。
具体的には、作業者の動きを撮影し、ストップウォッチと動画を見比べながら、作業要素に分解してサイクルタイムを測る、といった分析です。

この作業は、かなりの手間になります。
そこで今回は、撮影された動画から自動で「作業分析」を行うしくみを作ってみました。

動画を S3 に置くと、定型の作業分析レポート(作業要素の分解・サイクルタイム・問題点・改善提案)が出力されます。
使用したのは、Amazon Bedrock の Claude です。

構成は S3 と Lambda と Bedrock だけのサーバーレスで、CDK でデプロイできるようになってます。

題材(作業の動画)は、Hugging Face で公開されている一人称視点(エゴセントリック)の工場作業動画データセット builddotai/Egocentric-10K です。本記事では、この中の 4 本(プレス加工・組立など)を分析対象にしました。

以下は、その 4 本を 2×2 に並べて先頭 60 秒に切り出した紹介動画です(音声なし。左上から report_001 プレス/report_002 プレス/report_003 組立/report_004 プレス)。

https://www.youtube.com/watch?v=V1lN9hatAoA

そして、左上の作業動画から自動生成されたレポートが以下です。(他の3つの作業動画については§7で紹介)

最初に正直に書いておきますが、サイクルタイムは推定を含むため、本ツールは現場観察の初期分析段階に適しており、最終的な精密測定には別途検証が必要です(詳細は後述)。

あくまで、現場観察の「たたき台」を自動で用意する、という位置づけです。それでも、観点の抜け漏れを防ぎつつ一定品質のレポートを量産できる点には手応えがありました。

2 全体像とアーキテクチャ

Claude は画像(PNG / JPEG)や PDF、テキストの入力に対応していますが、動画ファイルはそのまま渡せません。そこで、動画を静止画フレームに分解してから Claude に渡しています。この分解から解析、レポート生成までを 1 本のパイプラインにしました。

001

処理の流れは次のとおりです。

  1. ffmpeg で動画をフレーム画像に分解する
  2. 複数フレームを 1 枚のコンタクトシート(タイル画像)にまとめて Bedrock の Claude へ渡す
  3. Claude が作業要素・サイクル・問題点・改善提案を JSON で返す
  4. その JSON からレポート(Markdown)とグラフ・模式図を生成し S3 に出力する

3 使い方

(1) デプロイ

git clone https://github.com/furuya02/bedrock-work-video-analysis
cd bedrock-work-video-analysis/cdk

pnpm install
pnpm exec cdk bootstrap          # 初回のみ
pnpm exec cdk deploy

デプロイ後、出力(Outputs)に入出力用の BucketName が表示されます。

003

Bedrock のモデル(Claude Opus 4.8)は AWS Marketplace 経由で提供されるため、初回呼び出しでアカウントに有効化される必要があります。本サンプルでは、Lambda 実行ロールに aws-marketplace:Subscribe / ViewSubscriptions を付与し、初回実行時に自動で有効化されるようにしています(有効化後は bedrock:InvokeModel だけで動作します)。

cdk/lib/stack.ts(抜粋)

fn.addToRolePolicy(new iam.PolicyStatement({
  actions: ["aws-marketplace:ViewSubscriptions", "aws-marketplace:Subscribe"],
  resources: ["*"],
}));

GitHub: cdk/lib/stack.ts

なお、モデルの利用まわりで 2 点つまずいたので補足します。

  • 東京リージョンのモデル指定: Opus 4.8 はオンデマンドで直接指定すると ValidationException になります。クロスリージョン推論プロファイル jp.anthropic.claude-opus-4-8 を指定して解消しています(利用可能な ID は aws bedrock list-inference-profiles で確認できます)。
  • モデルアクセス(Marketplace): アクセスが未有効だと初回呼び出しで AccessDeniedException になります。上記の Marketplace 権限を Lambda ロールに付与し、初回実行で自動有効化されるようにしています。

(2) 動画を置くとレポートが出る

BK=<出力された BucketName>

aws s3 cp sample.mp4 s3://$BK/input/sample.mp4
# 数分後
aws s3 ls  s3://$BK/output/sample/
aws s3 cp  s3://$BK/output/sample/ ./out/ --recursive

out/report.md と各グラフ・模式図・analysis.json が出力されます。

(3) クリーンアップ

pnpm exec cdk destroy

4 パイプライン

このパイプラインは、フレーム抽出に ffmpeg(ネイティブバイナリ)を、グラフ・模式図の描画に matplotlib(日本語フォント含む)を使います。ffmpeg のバイナリ同梱と、matplotlib 等の依存で zip 方式の展開後 250MB 制限を超えやすいことから、Lambda は zip ではなくコンテナイメージになっています。

(1) フレーム抽出とコンタクトシート化

先頭 60 秒を 2fps(0.5 秒間隔)で 120 コマ抽出し、幅 1024px に整えます。

ffmpeg -i input.mp4 -t 60 -vf "fps=2,scale=1024:-2" frames/f_%05d.jpg

ここで一つ制約があります。Bedrock の Converse API は 1 リクエストあたり画像 20 枚が上限です。120 コマをそのまま送れません。そこで、6 コマずつを 1 枚のタイル画像(コンタクトシート)にまとめ、各コマに通し番号を焼き込んで 20 枚に集約しました。タイルは 2048×1728px(約 3.5 メガピクセル)で、Bedrock の画像サイズ上限に収まります。

実際に生成されるコンタクトシートの例が以下です(report_001 の先頭 6 コマ。左上の黄色い数字が通し番号で、2fps なので 1→2 が 0.5 秒間隔です)。

002

(2) Bedrock(Claude)での解析

boto3 の Converse API で、コンタクトシートを画像として渡します。東京リージョンでは Opus 4.8 をオンデマンド直呼びできないため、クロスリージョン推論プロファイル(jp.anthropic.claude-opus-4-8)を指定しています。

# lambda/handler.py(要点抜粋)
content = [{"text": "作業動画のコンタクトシートを時系列で示します。各コマの数字が通し番号です。"}]
for m in montages:                       # 20 枚のタイル画像
    content.append({"image": {"format": "jpeg", "source": {"bytes": open(m, "rb").read()}}})
content.append({"text": PROMPT})         # 作業分析の指示(後述)

resp = bedrock.converse(
    modelId="jp.anthropic.claude-opus-4-8",
    messages=[{"role": "user", "content": content}],
    inferenceConfig={"maxTokens": 4000},
)
analysis = json.loads(re.search(r"\{.*\}", resp["output"]["message"]["content"][0]["text"], re.S).group(0))

GitHub: lambda/handler.py

プロンプトでは、作業要素の分解・サイクルタイム・7 観点の問題点・改善提案・作業エリアの配置(後述の模式図用)を JSON で返すよう指示しています。Claude が返した通し番号から、各作業要素の代表フレームを個別画像(高精細)として切り出し、スナップショットに使います。

プロンプトの要点は、次のような内容です。

  • 役割と出力: 「生産技術(IE)の作業分析者」として振る舞い、JSON だけを出力させる(余計な文章を出させない)。
  • サイクルの測り方: 左右の手は同時に別作業をしうるので、1 サイクルは各要素の単純合計ではなく「1 個が完成する周期」で測る、と明示(これが時間の過大評価を防ぐ)。
  • 正味/付随の定義: 正味作業は「素材・製品に付加価値を与える中核工程(加工・成形・締結・組付など)のみ」。運搬・投入・位置決め・取出しなどは付随作業、と定義(作業種別が変わっても通用するよう一般化)。
  • 6 つの判定項目: elements(要素・時間・正味/付随・代表コマ・左右の手・動線)/cycles_sec(実測サイクルをできるだけ全列挙)/utilization(稼働内訳%)/findings(7 観点を必ず点検し重大度付き)/improvements最低 3 件・定量効果つき)/layout(ゾーンの位置・種別)。
  • 控えめな見積り: 推測が難しい値は控えめに、とも指示(数値を盛らせない)。

GitHub: lambda/handler.py(PROMPT)

実際に返ってきた JSON(抜粋)が以下です(elements は作業要素、layout.zones は作業エリアの配置、cycles_sec は観測した各サイクルの秒数です)。

{
  "layout": {
    "zones": [
      { "key": "src", "label": "素材箱", "pos": "right", "kind": "source" }
    ]
  },
  "elements": [
    {
      "name": "プレス打抜",
      "desc": "スライドが下降し素材を打抜き・成形する",
      "time": 1.0,
      "type": "正味",
      "frame_index": 10,
      "left_hand": null, "right_hand": null,
      "arrow": null, "parallel": false
    }
  ],
  "cycles_sec": [3.0, 3.0, 3.5, 3.0, 3.5, 3.0, 3.5, 4.0, 3.0, 3.5]
}

この layout.zones から模式図を、elements からスナップショットと作業要素の内訳を、cycles_sec からサイクルタイムのヒストグラムを生成します。

GitHub: samples/report_001/analysis.json

この JSON を読むと、report_001 では 1 サイクルが「素材取り → 位置決め → 起動 → プレス打抜 → 完成品排出/次素材準備」に分解され、付加価値を生む正味作業はプレス打抜のみ(素材投入と完成品排出は左右の手で並行)と解析されています。サイクルタイムは cycles_sec から中央値 約 3.2 秒(最速 3.0 / 最遅 4.0 / 標準偏差 0.3 秒)でした。

(3) レポート生成

返ってきた JSON から、Python でレポート本文・グラフ・模式図を組み立てます。レポートの構成(章立て・チェックリスト・グラフ)は共通です。

サイクル図の作り方

なお、図を作成しているのはClaudeではありません。Claude が返すのは、あくまで数値・ラベル・位置キーワードといった構造化データだけで、実際の作図は report_builder.py(matplotlib)が決定論的に行っています。たとえば本節の後半で示す「1サイクルの流れ」図は、JSON の elements(要素名・所要時間・種別)を、あらかじめ決めた座標に矩形と矢印で配置して描いています。

# lambda/report_builder.py(_cycle:要点抜粋)
pos = [(5.0, 7.6), (7.7, 5.0), (5.0, 2.4), (2.3, 5.0)]   # 4要素を上→右→下→左に固定配置
for i in range(min(len(elems), 4)):
    e = elems[i]; x, y = pos[i]
    c = "#C0392B" if e.get("type") == "正味" else palette[i]  # 正味作業だけ赤で強調
    ax.add_patch(FancyBboxPatch((x-1.35, y-0.7), 2.7, 1.4, fc=c, ec="#222", ...))  # 箱
    ax.text(x, y+0.18, f'{i+1} {e["name"]}', ...)            # 要素名(JSONのname)
    ax.text(x, y-0.35, f'{e["time"]}秒', ...)                # 所要時間(JSONのtime)
for i in range(n):                                           # 箱どうしを矢印でつなぐ
    ax.add_patch(FancyArrowPatch(pos[i], pos[(i+1) % n], arrowstyle="-|>", ...))

模式図は「配置キーワード」を座標に変換して描く

作業エリアの模式図も同じ考え方です。Claude は各ゾーンを "pos":"right"(素材箱=右)のような位置キーワードで返すだけで、コード側が right → (8.2, 5.2) のように座標へ変換し、種別(kind)に応じた色や、手(left_hand/right_hand)・動線(arrow)を重ねて描きます。

# lambda/report_builder.py(要点抜粋)
POS = {"top": (5.0, 8.2), "center": (5.0, 5.2), "left": (1.8, 5.2),
       "right": (8.2, 5.2), "bottom": (5.0, 2.3), ...}          # キーワード→座標
KIND_COLOR = {"machine": "#7A7A7A", "source": "#BFD3E6", "dest": "#E0CDAF", ...}
x, y = POS.get(zone["pos"], (5.0, 5.2))                          # "right" を座標に
ax.add_patch(FancyBboxPatch(..., fc=KIND_COLOR.get(zone["kind"])))  # 種別で色分け

この「AI は判断(データ)に専念し、描画は手元のコードが担う」構成にしたのは、図のレイアウトや配色が毎回ブレず、作業が変わっても JSON を差し替えるだけで同じ様式の図を出すためです。逆に、位置キーワードが実際の映像と食い違えば図もズレるため、模式図は「AI の空間認識を人が確認するための参考図」という位置づけにしています。

次の図は、report_001 で生成された図です。elements から起こした「1サイクルの流れ」図と、cycles_sec から描いたサイクルタイムのばらつき(分布)です。

004

005

次は作業エリアの模式図です。一人称かつ魚眼の映像はそのままでは分かりにくいため、代表フレーム(スナップショット)に加えて、作業エリアを真上から見た模式図を自動生成しています。前述のとおり、これは Claude が読み取った配置(素材箱=右、完成品箱=左、など)を描いたもので、AI の空間認識を可視化した参考図です。

006

この図は「AI の理解が実際の映像と合っているか」を人が一目で確認する用途に使えます。

最後に稼働内訳です。正味作業 28% / 手待ち・取り置き 47% / その他 25% で、機械のプレス動作と手作業が直列化して手待ちが多いことが読み取れます。これに対し、自動送り・シュート排出による並行化などの改善提案が、定量的な期待効果とともに出力されました。

5 分析の品質

作業や動画が変わっても分析の質が落ちないよう、二つの指示を入れています。

(1) 問題点検出の観点チェックリスト

問題点の抽出を勘に任せると観点が抜け落ちる可能性があります。そこで 安全・動作のムダ・手待ち・ばらつき・品質・人間工学・運搬配置 の 7 観点を固定し、毎回すべて点検させています。該当が無くても「該当なし」と明記させ、観点漏れを防いでいます。report_001 では、打抜時に手が金型可動部へ入っている点を、安全の重大度「高」として検出していました。

(2) 効率化・改善提案の必須化

検出した問題に対して改善提案を必ず添える仕様とし、最低 3 件を必須にしました。レポート生成側でも件数を検査し、満たない場合は生成を停止させています。

# lambda/report_builder.py(要点抜粋)
MIN_IMPROVEMENTS = 3
if len(improvements) < MIN_IMPROVEMENTS:
    raise ValueError(f"効率化・改善提案が {len(improvements)} 件(必須: 最低 {MIN_IMPROVEMENTS} 件)")

各提案には「対応する観点」と「定量的な期待効果」を必ず持たせています。

6 精度への工夫と限界

(1) 精度を上げるために効いたこと

いくつかの試行で、特に効いたと感じたのは次の点です。

  • モデル: 当初は打抜工程を取り違えることがありましたが、上位モデル(Claude Opus 4.8)にすると作業の解釈が安定しました。
  • 連続コマを渡す: 数分から等間隔で数枚だけ抜くとサイクルの周期が測れず、サイクルタイムが実測の倍近くに出ました。60 秒を連続 2fps でコンタクトシート化して渡すことで、実測に一致しました。
  • 両手の並行動作を明示: 「左右の手は同時に別作業をしうる。サイクルは 1 個が完成する周期で測る」と指示することで、時間の過大評価が是正されました。
  • 解像度: タイルのコマに実解像度が乗るよう、入力を 720p にしています。

(2) 限界と感じたこと

今の仕組みで限界と感じた事項です。

  • サイクルタイムは推定を含む: 1fps〜2fps の時間分解能に依存し、1 秒未満の動作は測れません。とくに長いサイクルの作業では 60 秒の窓に数サイクルしか入らず、モデルがサイクル数を推定で埋めることがあります(時間の値は妥当でも、観測数が窓長を超えて出る)。長サイクルは窓を延ばす(例: 120 秒 @ 1fps)などの調整が要ります。
  • 空間認識は人と食い違うことがある: 配置や手の左右は AI の解釈です。だからこそ模式図で人が確認する設計にしていますが、鵜呑みにはできません。
  • 非周期・隠れの多い作業は苦手: 明確な繰り返しが無い作業や、手・加工点が隠れる映像では精度が出せません。

7 同じ仕組みで別の作業もやってみました

同じパイプラインに、別の作業者・別作業の動画を流してみた結果です。プロンプトは特定の作業に依存しないよう一般化されています。

  • report_002: フットプレスによる打抜き/曲げ加工(プレス系)
  • report_003: 座り作業でのねじ・部品組付(組立/締結) ← プレスとは異なる作業
  • report_004: 板金プレス(両手起動)

とくに report_003 は、プレスではない手作業の組立ですが、正味作業を「組付・締結」と正しく捉え、部品箱の配置や素手での鋭利部品の扱い(切創リスク)といった、その作業ならではの観点・改善提案が出力されました。作業種別が変わっても、同じ仕組みで一定のレポートが得られています。

一方で、組立や板金プレスは 1 サイクルが 10 秒前後と長く、前述のとおり 60 秒窓ではサイクル数を測りきれませんでした。別作業へ広げる場合、サイクル長に応じた窓長の調整が必要であることが確認できました。

8 最後に

動画を置くだけで、作業要素の分解からサイクルタイム・問題点・改善提案までを載せた定型レポートが自動で出てくるところまで作ることができました。観点チェックリストと提案の必須化により、作業が変わっても一定の品質と観点網羅を保てています。

  • できたこと: 定型レポートの自動生成、7 観点の網羅、改善提案の必須化、別作業への一定の汎用、CDK による再現可能なデプロイ
  • できていないこと: サイクルタイムの厳密な計測、長サイクル作業での窓調整、空間認識の完全な正しさ

なお、全ての作業に対応するのではなく、対象とする作業を分析しやすいようにプロンプトを工夫すること(作業単位に最適化)を考慮にいれれば、更に正確な分析も可能になるのではと思いました。

繰り返しになりますが、現時点では現場観察のたたき台を自動で用意する道具という位置づけです。それでも、ゼロから作業分析を起こす手間を大きく減らせる感触がありました。

サンプルコードは以下で公開しています。


製造業のクラウド活用とデジタル化を支援します

クラスメソッドの専門家による包括的なクラウド導入とデジタル化支援で、製造業の業務効率を最大化しましょう。AWSの導入から運用、最適化まで、最新技術と豊富な知見であらゆる課題に対応します。生産ラインのデジタル化やデータ活用、IoTの導入事例もございます。ぜひ、弊社の実績をご覧ください。

製造業界での支援内容を見る

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事