Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PIXIV SUMMER BOOT CAMP 2022 成果発表「GIFから12倍速くする」
Search
Mutsuha Asada
September 28, 2022
Technology
0
23
PIXIV SUMMER BOOT CAMP 2022 成果発表「GIFから12倍速くする」
Mutsuha Asada
September 28, 2022
Tweet
Share
More Decks by Mutsuha Asada
See All by Mutsuha Asada
❄️ tmux-nixの実装を通して学ぶNixOSモジュール
momeemt
1
170
Wasmで拡張できる軽量マークアップ言語 Brack
momeemt
0
78
❄️ NixOS/nixpkgsにSATySFiサポートを実装する
momeemt
2
220
Intel系FPGA上へのRISC-Vプロセッサの実装
momeemt
0
130
情報科学若手の会 2024 LT「WebAssemblyで拡張可能な軽量マークアップ言語の開発」
momeemt
0
37
Nixでつくるdotfiles
momeemt
1
39
情報特別演習I 最終発表「理工学の紙書籍を用いた学習の効率を向上させるインタフェース」
momeemt
0
32
SATySFi Conf 2023「SATySFiを使って学類新歓冊子を発行した」
momeemt
0
22
主専攻実験(深層学習を用いたCG・画像処理)最終成果報告
momeemt
0
33
Other Decks in Technology
See All in Technology
Amazon Bedrockで実現する 新たな学習体験
kzkmaeda
1
400
_第3回__AIxIoTビジネス共創ラボ紹介資料_20250617.pdf
iotcomjpadmin
0
140
CSS、JSをHTMLテンプレートにまとめるフロントエンド戦略
d120145
0
220
CI/CDとタスク共有で加速するVibe Coding
tnbe21
0
230
原則から考える保守しやすいComposable関数設計
moriatsushi
3
500
【TiDB GAME DAY 2025】Shadowverse: Worlds Beyond にみる TiDB 活用術
cygames
0
860
Agentic Workflowという選択肢を考える
tkikuchi1002
1
380
プロダクトエンジニアリング組織への歩み、その現在地 / Our journey to becoming a product engineering organization
hiro_torii
0
110
BigQuery Remote FunctionでLooker Studioをインタラクティブ化
cuebic9bic
2
230
Welcome to the LLM Club
koic
0
130
標準技術と独自システムで作る「つらくない」SaaS アカウント管理 / Effortless SaaS Account Management with Standard Technologies & Custom Systems
yuyatakeyama
2
1k
20250625 Snowflake Summit 2025活用事例 レポート / Nowcast Snowflake Summit 2025 Case Study Report
kkuv
1
200
Featured
See All Featured
Stop Working from a Prison Cell
hatefulcrawdad
270
20k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Documentation Writing (for coders)
carmenintech
71
4.9k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
48
5.4k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
What's in a price? How to price your products and services
michaelherold
245
12k
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Testing 201, or: Great Expectations
jmmastey
42
7.5k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Making the Leap to Tech Lead
cromwellryan
134
9.3k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
34
3k
Transcript
GIFから12倍速くする ImageFluxコース PIXIV SUMMER BOOT CAMP 2022 筑波大学 momeemt /
浅田睦葉 2022.9.28
2 自己紹介 • 筑波大学 情報学群 情報科学類 1年次 • Nim /
FFmpeg • 趣味: インディーズバンドとお笑い ◦ 35.7とダウ90000が好きです • Twitter: @momeemt momeemt ImageFluxコース
3 nontanさん usaさん terryさん hayaさん 配信技術部 メンター サブメンター
4 H.264エンコーダを利用して GIFアニメーションをmp4に変換する
5 • GIFとは複数枚の画像をコマ送りにしてアニメーションにできる 画像ファイルフォーマットの こと • Webブラウザでも標準的にサポート • ImageFluxもサポートしている GIF?
▲こういうの
6 • H.264が行うフレーム間予測というメチャクチャ賢い圧縮ができない ◦ → ファイルサイズが大きくなるので配信コストが高い • エンコードが遅い ◦ どうして...
GIFの問題点 地球も泣いている
• H.264とは動画圧縮規格の1つ • 「.mp4」「.mov」「.m4v」などおなじみ(?)の拡張子を持つ動画は H.264コーデックによっ てエンコード(圧縮)されている • 軽い!速い! 7 H.264?
8 • FFmpegは映像や音声を処理できる伝統のライブラリ • 膨大なコーデックやファイル形式、メディアをサポートしている • コマンドラインツールとしては有名だが libavcodec等のAPIを直接叩くことも ◦ 今回はこっち
FFmpeg
9 • nasm・yasm・libx264・FFmpegをインストール インストールバトル
10 • ビルド時間がえらいことに(15分半) 長すぎ
11 • H.264コーデックを手に入れる • エンコードに必要な設定を行う • 書き出し先である映像ストリームを準備する • フレームをエンコードしてパケットに格納して書き出す H.264エンコーダを呼び出す
12 • cgoはCとGoを相互運用する仕組み ◦ FFmpegの各種APIはCで記述されているのでこれを使って呼び出す ◦ GoのFFmpegラッパーではうまくいかなかったので途中で使うのをやめた cgo
13 あとは根気 • これはもうC言語
14 • VLCやブラウザで視聴可能なmp4ファイルを出力できた • QuickTimeではブラックスクリーンになり見れない ◦ 気難しい できた mp4になった地球 困る
15 • ImageFlux上でGIFをmp4に変換する • URLで f=mp4 というパラメータを与えるとmp4が返ってくるようにしたい ImageFluxでmp4変換をサポートする
16 • これまでは書き出すために avio_open 関数を呼んでいた ◦ URLを受け取って書き出し先を確立する • しかし、ImageFluxではHTTPのレスポンスとして書き出す必要があるので、 io.Writer
に書 き出さなければならない • そこでカスタムな AVIOContext を作成して io.Writer を繋ぎ合わせる I/Oを繋ぎ合わせる
AVIOContext *allocIOContext(void *bridge) { int bufferSize = 4096; uint8_t *buffer
= (uint8_t *)av_malloc(bufferSize); return avio_alloc_context( buffer, bufferSize, 1, bridge, 0, golibmp4BridgeWriterWrite, golibmp4BridgeSeek ); } void freeIOContextBuffer(AVIOContext *ctx) { av_free(ctx->buffer); } I/Oを繋ぎ合わせる C側から関数ポインタを渡す 17
• AVIOContextは書き込み関数だけでなくシーク関数を呼んでいる 18 I/Oを繋ぎ合わせる f544a9e55d239e42d74c9a16971e4b234da64441cd7bd 9e17c199b60b09fbe3741fda6110ee2fd16514d88f280b 62c1989204ba2db16d36d650419aeb04e4b5bc762b81 87f91c5d7845… 基本的には最初から順番に書き込んでいくが...
• AVIOContextは書き込み関数だけでなくシーク関数を呼んでいる 19 I/Oを繋ぎ合わせる f544a9e55d239e42d74c9a16971e4b234da64441cd7bd 9e17c199b60b09fbe3741cd50…fda6110ee2fd16514d8 8f280b62c1989204ba2db16d36d650419aeb04e4b5bc7 62b8187f91c5d7845 ファイルの途中に巻き戻って書き出すこともある
• ImageFluxは io.Writer を受け取る関数が処理の基本単位になっている ◦ io.Writer はシークできることが保証されていないのでシークできない • エンコードする時にシーク可能なバッファに書き込んで、まとめて書き出す ◦
メンターのnontanさんが seekbuf を実装してくださった 実装しておきました 20 I/Oを繋ぎ合わせる ありがとうございます🙏
21 動いた ~/c!/f=mp4/testdata/images/rotating_earth.gif
22 • 利用しやすいOpenH264に差し替える • libopenh264をビルドしてインストール(pkg-configファイルの生成) • libopenh264が生成した共有ライブラリを削除して Ciscoがビルドして頒布している共有ラ イブラリに差し替える •
OpenH264を有効にしてFFmpegをビルド OpenH264への差し替え
23 • GIFよりどれくらい速くなったのか • GIFエンコードとmp4エンコードのベンチマークを書いて計測する 計測! 1回の実行に561ミリ秒 GIFエンコード
• GIFよりどれくらい速くなったのか • GIFエンコードとmp4エンコードのベンチマークを書いて計測する 24 もう速い mp4エンコード 1回の実行に69ミリ秒 6.3倍
25 お得 ファイルサイズも半分少しになっている
26 • しかしメモリ確保を43倍やっているのでもう少し減らしたい 富豪すぎた mp4エンコード 1回の実行に176万回もメモリを確保している
27 • NRGBAをYUV420Pに変換する時にメモリアロケーション回数が跳ね上がっていた エンコード最適化
28 • color.NRGBA 型が color.Color 型にBoxingされる際にメモリアロケーションがされまくっ ていた ◦ → image.NRGBA
型にアサーションすることでアロケーションを回避 エンコード最適化
• 元のGIFエンコードよりも 12.2倍 高速になった • また、メモリ確保回数はGIFエンコードと比べて 0.013% になった 29 結果
1回の実行に46ミリ秒 爆速
もっと! 30 ※ 最終日はずっとチューニングしていた
• 色空間の変換で毎フレーム確保されていたバッファを使い回す • 元のGIFエンコードよりも 14.8倍 高速になった 31 NRGBA32→YUV420P変換 1回の実行に38ミリ秒
• 色空間の変換で23ms、フレームの書き込みで15msかかっている • どちらかを改善したい 32 速度的なボトルネック 変換部分のありなしで 2桁も変わる
• 自前の色空間変換を捨てて libswscale を使ってみる ◦ SWS_FAST_BILINEAR フラグで変換するとかなり速かった(約 17ms) • 元のGIFエンコードよりも
19.1倍 高速になった 33 libswscaleを使う 1回の実行に29ミリ秒
• なったが、かなり変換時間にはブレがある ◦ 自前の場合は安定して37ms〜42msかかっていた ◦ swscaleでは27〜32msかかることは多いが、たまに60msになったりする 34 libswscaleを使う 1回の実行に29ミリ秒
35 感想 • 複数の環境で問題なく動作すること、いずれ本番環境に乗せることを見据えて品質を保 つことなどを強く意識させられた 8日間でした • FFmpegを延々と触っていられて楽しかったです ◦ 実装のためにドキュメントを普段よりじっくりと読めたので解像度がなんとなく上がった
気がします • シェルが書けないとこんなに辛いんだなと思いました ◦ 8日間で一番苦労したのはシェルスクリプトでした
36 8日間ありがとうございました!!! 最後に メンターのnontanさん、人事のkamikoさん、配信技術部のみなさま、 お世話になりました、ありがとうございました!