去年、「Internal Hack Day 19」というイベントに参加して、面白いアプリを作ったので紹介します。

※特許出願の関係で、去年参加したハッカソンの内容になります。

作品

DEMO動画 (一部カット編集済)

作品の紹介画像

ショート動画で良さそうな商品が紹介されてるとついつい見ちゃうんですよね。
目を引く楽しい演出気になる部分だけをピックアップして紹介、そんな動画をすでにある情報 (Webの商品ページ) から自動生成できたら便利なのではということで、「5秒ショッピング」というアプリを作りました。

技術

24時間のハッカソンということもあり、シンプルに作りたいということで、サーバーを使わず、すべてiPhone上で動くiOSアプリとして作りました。

外部ライブラリも特に使わず、標準技術のみ。

  • SwiftUI
  • AVFoundation
  • CoreImage
  • Metal
  • CoreML / CreateML

自分は主に動画生成やAI部分を担当したので、そのあたりの技術について紹介します。

情報ソースの取得

WebViewで商品ページを開いて、そのページのHTMLから動画生成に必要な情報を取得しています。

特定のサイトにフォーカスして気合で商品名や商品画像、レビューなどのデータを取得しましたが、今ならGPT-4などの技術でよしなに取得させることができそうです。

商品画像のAI厳選

ショッピングサイトの商品画像には商品イメージがわかりにくい、成分表示などが含まれる場合があります。
必要な情報ではあるのですが、今回のショート動画の内容としては映えないので、自動で取り除くことにしました。

不要な画像を削除

これにはCoreML / CreateMLを利用して特化した分類モデルを作成し、ふるい分けをしました。

動画生成

動画は端末内で生成しています。

AVAssetWriterというAPIを使うと、動画編集アプリのように動画を結合したり、音声を載せたりする編集ができます。

自分はVCamというMacでVTuberのようになれるアプリを作っているのですが、その中に録画機能があり、その時に実装した技術を応用することで早く実装できました。

クリップの作成

動画生成を実装しやすくするために動画編集アプリにあるような「クリップ」という概念を実装上導入し、料金のテキストや画像などをクリップとして扱いました。

ざっくりなコードとしては下記です。

1
2
3
4
5
6
struct PriceClip: VideoClip {
    ...
    func image(elapsed: TimeInterval) async -> CIImage {
        // 時間に応じて料金表示を描画する
    }
}
料金表示

料金表示のレイアウト自体はSwiftUIで実装し、そのViewを CIImage に変換して動画としてレンダリングしています。
そうすることで、Xcode Previewsでサクッと描画結果を確認できるので便利でした。

エフェクト

ただ商品画像が出てくるだけだと、すぐ飽きてしまって面白くないので、TikTokのように楽しいエフェクトやアニメーションを付けるようにしました。

エフェクトはMetalやCoreImage、シンプルな計算などで実装しています。
これは先ほど紹介した VideoClip に適用する VideoEffect 型を作成して実装しました。

1
2
3
4
5
6
struct GlitchEffect: VideEffect {
    ...
    func apply(_ image: CIImage, numberOfFrames: Int, currentFrame: Int) -> CIImage {
        // 動画のフレームをグリッチさせる
    }
}

シンプルに1フレームごとにエフェクトを掛けていますが、iPhoneは高性能なので数秒で動画は生成されました。

感想

去年作ったものではありますが、今見ても結構面白いアプリが作れたとブログを書きながら思いました。

今のAI技術に一部を置き換えれば、もっと面白くて質の高い動画が作れると確信しているので、機会があればそういうものを作ってみたいです。

ハッカソンは気になっている技術を締め切りドリブンで本気になって試せるのがとても良いです。短時間で作るのはものづくりのモチベーションを上げるのにも良いので、Done is better than perfect の精神でこれからも色々作っていきたいです。

関連リンク