Amazon Web Services ブログ

あなたが主役の自動ビデオ編集!

何時間ものビデオ映像の中で特定の人物を見つけたいと思ったことはありませんか?

21 才のお誕生日パーティー用にビデオを準備していて、お誕生日を迎える子供の楽しい思い出を見つけたいのかもしれません。特定の社員が最後の勤務日に何をしたかを見るためにビデオ映像を探し回っているのかもしれませんし、ネイサンズ国際ホットドッグ早食い選手権での自分の活躍のハイライト映像を作りたいのかもしれません。

このブログ記事では、Amazon Rekognition Video と Amazon Elastic Transcoder の機能を組み合わせて、長時間のビデオを所定の人物の全映像を映し出すハイライトビデオに自動で変換する方法を学んでいただけます。

シンプルなデモ

このプロセスを説明するため、私は AWS の Day in the Life of an AWS Technical Trainer ビデオを使用します。ビデオを見ると、カメラに向かって話す人、お客様を訓練する人、そしてオフィス内を歩く人が数人が出演しているのがわかります。

このビデオは、このブログで後ほど説明するプロセスで処理されたもので、このプロセスは具体的に選択した人物のビデオを自動で作成します。これらのアウトプットビデオを見て、最終版を確認してください。

現に、MJ のビデオは 2 つの個別のシーンが自動的に結合されたため、単一の連続した撮影ショットのように見えます。シーンがどこでつながれているかは、ビデオをじっくり見なければわかりません!

プロセス

これがハイライトビデオを作成するために使用された全体的なプロセスです。

  1. Amazon Rekognition で顔コレクションを作成し、認識するべき人を教える。
  2. Amazon Rekognition Video を使って、保存されたビデオファイル内の顔を検索する。
  3. 顔が認識された箇所の個々のタイムスタンプを収集して、それらを定義された長さのクリップに変換する。
  4. Amazon Elastic Transcoder を使用して新しいビデオを結合する。

各ステップの説明は次のとおりです。

ステップ 1: 顔コレクションの作成

Amazon Rekognition の顔コレクションには、写真とビデオの中で認識したい顔についての情報が含まれています。これは、ソフトウェア SDK を使用する、または AWS コマンドラインインターフェイスを使用して CreateCollection を呼び出すことで作成できます。私は create-collection コマンドを使用しました。

$ aws rekognition create-collection --collection-id trainers

この後、index-faces コマンドを使用して、イメージを直接渡す、または Amazon S3 に保存されたオブジェクトを参照することによって個々の顔をコレクションにロードできます。

$ aws rekognition index-faces
--collection-id trainers 
--image "S3Object={Bucket=<my-bucket>,Name=john.jpg}" 
--external-image-id John

ExternalImageID は、顔にフレンドリ名を付けるために使用できます。そうすると、その顔が写真またはビデオで検知されるときにこの ID が返されます。

私のビデオには、スタッフディレクトリから各人物の個人写真を取得、またはビデオのフレームから彼らの画像をコピーして取得しました。次に、index-faces コマンドを実行して、各人物の顔をロードしました。

Amazon Rekognition は実際のところ、検知された顔を保存しません。その代わり、基盤となる検知アルゴリズムがまずインプットイメージ内で顔を検知し、顔立ちを特徴ベクトルに抽出します。このベクトルはバックエンドデータベースに保存されます。Amazon Rekognition は、顔の一致操作と検索操作の実行時にこれらの特徴ベクトルを使用します。

ステップ 2: ビデオでの顔検索の実行

Amazon Rekognition は、写真、保存されたビデオ、およびストリーミングビデオで顔を認識できます。このプロジェクトでは Amazon S3 に保存されたビデオ内の顔を見つけたかったので、StartFaceSearch を呼び出しました。

$ aws rekognition start-face-search
--video "S3Object={Bucket=<my-bucket>,Name=trainers.mp4}"
--collection-id trainers

顔の検索は、ビデオの長さに応じて数分かかります。希望に応じて、検索が完了したときに Amazon Simple Notification Service トピックに通知を送信しすることができ、その後、Amazon Simple Notification Service がフォローアッププロセスをトリガーできます。

顔検索の結果は、人、タイムスタンプ、および顔の一致のリストです。

{
  "Persons": [
    {
      "Timestamp": 7560,
      "FaceMatches": [
        {
          "Face": {
            "BoundingBox": {
              "Width": 0.6916670203208923,
              "Top": 0.1909089982509613,
              "Left": 0.14166699349880219,
              "Height": 0.46111100912094116
            },
            "FaceId": "6b62481e-06fa-48ea-a892-b8684548958b",
            "ExternalImageId": "John",
            "Confidence": 99.99750518798828,
            "ImageId": "ad98b04a-6b06-5ca5-b5ce-4db389c65c18"
          },
          "Similarity": 89.65567016601562
        }
      ],
    },
    {
      "Timestamp": 7640,
      ...

ビデオで検知された顔のすべてがリストされますが、Amazon Rekognition Video は、顔コレクションに一致する顔を見つけるたびに顔のフレンドリ名を含めます。このため、私は「John」という ExternalImageID があるレコードを探すだけですみました。

信頼度レーティング (上記では 99.99%) は、誤一致の確立を低減させるためにも使用できます。

顔検索による出力は、かなり大きくなる可能性があります。私の 3 分 17 秒のビデオでは、顔が見つかった箇所の 984 タイムスタンプを提供し、そのうちの 124 がフレーム内に存在するとして「John」を識別しました。

ステップ 3: タイムスタンプのシーンへの変換

最後のステップは、指定した人物が存在するシーンだけを映し出すアウトプットビデオの作成です。しかし、顔検索の出力は、その人物が登場する箇所のタイムスタンプのリストにすぎません。では、これらのタイムスタンプに基づいて新しいビデオを作成するにはどうすればよいでしょうか?

その答えは、Amazon Elastic Transcoder の使用です。これには、複数のクリップを組み合わせて単一のアウトプットビデオを作成する機能があります。これはクリップの結合として知られています。クリップは、複数のソースビデオ、または私の場合は同じインプットビデオの複数の部分から得ることができます。

Amazon Rekognition Video からのタイムスタンプを Elastic Transcoder 用のインプットに変換するため、私は以下を行う Python スクリプトを書きました。

  1. GetFaceSearch を呼び出すことによって顔検索の結果を取得する。
  2. 指定された人物が登場するたびにタイムスタンプを抽出する。
    [99800, 99840, 100000, 100040, ...]
  1. タイムスタンプをその人物が登場するシーンに変換し、各シーンの開始タイムスタンプと終了タイムスタンプを記録する。
    [(99800, 101480), (127520, 131760), ...]
  1. シーンを Elastic Transcoder で必要とされる形式に変換する。
    [
      {'Key': 'trainers.mp4', 'TimeSpan': {'StartTime': '99.8', 'Duration': '1.68'}},
      {'Key': 'trainers.mp4', 'TimeSpan': {'StartTime': '127.52', 'Duration': '4.24'}},
      ...
    ]
'''
Extract timestamps from Amazon Rekognition Video Face Search
Then use Amazon Elastic Transcoder to stitch the clips together
'''

import boto3

# Connect to Amazon Rekognition
client = boto3.client('rekognition', region_name = 'ap-southeast-2')

# Retrieve the face search results
person_to_find = 'Karthik'
timestamps=[]

search = client.get_face_search(JobId='...', SortBy='INDEX')

while (True):
  for person in search['Persons']:
    try:
      for face_matches in person['FaceMatches']:
        if face_matches['Face']['ExternalImageId'] == person_to_find:
          timestamps.append(person['Timestamp'])
    except KeyError:
      pass

  # Retrieve the next set of results
  try:
    next_token = search['NextToken']
    search = client.get_face_search(JobId='...', SortBy='INDEX', NextToken = search['NextToken'])
  except KeyError:
    break

'''
The timestamps array now looks like:
[99800, 99840, 100000, 100040, ...]
'''

# Break into scenes with start & end times
scenes=[]
start = 0

for timestamp in timestamps:
  if start == 0:
    # First timestamp
    start = end = timestamp
  else:
    # More than 1 second between timestamps? Then scene has ended
    if timestamp - end > 1000:
      # If the scene is at least 1 second long, record it
      if end - start >= 1000:
        scenes.append((start, end))
      # Start a new scene
      start = 0
    else:
      # Extend scene to current timestamp
      end = timestamp

# Append final scene if it is at least 1 second long
if (start != 0) and (end - start >= 1000):
    scenes.append((start, end))

'''
The scenes array now looks like:
[(99800, 101480), (127520, 131760), ...]
'''

# Convert into format required by Amazon Elastic Transcoder
inputs=[]
for scene in scenes:
  start, end = scene
  inputs.append({
    'Key': 'trainers.mp4',
    'TimeSpan': {
      'StartTime': str(start/1000.),
      'Duration': str((end-start)/1000.)
    }
  })

'''
The inputs array now looks like:
[
  {'Key': 'trainers.mp4', 'TimeSpan': {'StartTime': '99.8', 'Duration': '1.68'}},
  {'Key': 'trainers.mp4', 'TimeSpan': {'StartTime': '127.52', 'Duration': '4.24'}},
  ...
]
'''

# Call Amazon Elastic Transcoder to stitch together a new video
client = boto3.client('elastictranscoder', region_name = 'ap-southeast-2')

job = client.create_job(
  PipelineId = '...',
  Inputs=inputs,
  Output={'Key': person_to_find + '.mp4', 'PresetId': '...'}
)

スクリプトは、アウトプットビデオを作成するために Elastic Transcoder の create-job コマンドを呼び出して終了します。数秒後、私の Amazon S3 バケットにビデオが表示されます。表示されたら、異なる人物に固有の別のビデオを作成するために、その人物の名前を使ってスクリプトを実行します。

これが、あなただけのビデオであなたが主役になれる方法です!


今回のブログ投稿者について

John Rotenstein は、アマゾン ウェブ サービスのシニアテクニカルトレーナーで、お客様が AWS のサービスの使用において実践的な経験を得ることができる体験型ラボの作成を専門としています。John はオーストラリアのシドニーに住んでおり、Escape Rooms が大好きです。