「 GIFを維持できるのは、Netscapeが追加したループアニメーションです。 NetscapeがブラウザにGIFサポートを追加していなかった場合、GIFは1998年に死んでいたでしょう。 」
-アレクサンダー・トレバー、
CompuServeのGIFチームリーダー
今年6月のGIFは25周年を迎え、今日ではインターネット上で配信される最も古いグラフィック形式です。 週末に面白いアニメーションGIFを見ることに専念すると、それらのうちのいくつかは音ではるかに良くなることを理解しています。 アニメーションをサウンドでループさせるための現在のすべてのソリューション(例: coub.com 、 gifsound.com )はGIFを放棄することを提供しますが、これはオプションではありません。 そして、この非常に重要な問題を解決するために、週末にgifを見るのを犠牲にすることにしました。
リンクからの音があるインターネットGIFの最初。 青いボタンをクリックしてから、GIFをクリックする必要があります。 プレーヤーは、最新のブラウザー(最新のFirefoxおよびChromeでテスト済み)で動作するはずです。
カットの下に手掛かりはありませんが、標準の拡張機能を作成し、コンバーターとプレーヤーを作成するプロセスがあります。
1987年以来、GIF形式には2つの重要な変更しかありません。
- 89年に、フォーマットの2番目のバージョン(GIF 89aと呼ばれる)がリリースされました。 画像間の遅延を指定することが可能になりました(1つのファイルのいくつかの画像は最初のGIF 87a形式でした)。 サードパーティの開発者は、独自のブロックをファイルに追加できるようになりました(アプリケーション拡張ブロック)。
- 90年に、Netscapeは独自のブロックを追加しました。これにより、アニメーションを繰り返す回数を指定できます。
フォーマット拡張の開発
前述のように、GIF 89a標準では、アプリケーションがデータをGIFファイルに配置できます。 アプリケーション拡張ブロックの形式:
サイズ、バイト | 内容 |
---|---|
2 | アプリケーション拡張ブロックヘッダー(常に0x21、0xFF) |
1 | ブロックサイズ(常に11) |
8 | アプリケーションID |
3 | アプリケーション認証コード(特定のアプリケーションによってブロックが作成されたことを確認するために使用できます) |
* | ネストされたデータブロック |
1 | ブロックエンドポインター(0x00) |
ここにWAVEファイルのヘッダーを合わせてみましょう:
サイズ、バイト | 内容 |
---|---|
4 | ファイルヘッダー(常に「RIFF」) |
4 | データサイズ |
4 | データ形式(WAVEファイルの場合-「WAVE」) |
ブロックサイズはGIF形式で制御されるため、ヘッダーからデータサイズのフィールドを削除し、アプリケーション識別子に「RIFFWAVE」と書き込みます。 WAVEファイルの残りは、ネストされたGIFブロックとして書き込まれます。
画像のある最初のブロックの直前に音声付きのブロックを挿入します(実際、どこにでも挿入できます)。
コンバーター開発
入力コンバーターはGIFおよびWAVEファイルを受け入れ、出力はRIFFWAVEブロック付きのGIFを提供します。 google codeでソースコードを確認できます 。
コードは非常に単純で、WAVEファイルを読み取り、そこからGIFブロックを作成します。 次に、gifファイルを読み取り、すべてのブロックを書き込みます。最初のブロックが画像とともに見つかったら、すぐに音声付きのブロックを挿入します。 コードの最も重要な部分は、WAVEファイルをGIFブロックに変換することです。
def get_wav_block(file): # (signature, size, format) = unpack('4sI4s', file) if signature != 'RIFF': raise Exception('Not a RIFF file') if format != 'WAVE': raise Exception('Not a WAVE file') data = file.read(size - 4) # wave_block_header = struct.pack('BBB8sBBB', 0x21, 0xff, 11, 'RIFFWAVE', 0, 0, 0) data_subblocks = [wave_block_header]; # 255 for i in range(0, len(data) // 255): data_subblocks.append(chr(0xff)) data_subblocks.append(data[i*255:(i + 1)*255]) if (len(data) % 255) > 0: rest = len(data) % 255 data_subblocks.append(chr(rest)) data_subblocks.append(data[-rest:]) # data_subblocks.append(chr(0)) return ''.join(data_subblocks)
音声付きのGIFを作成する
アニメーションgifの作成:
# ffmpeg ffmpeg -ss 0:00:9.73 -t 2.86 -i warlus.webm -s 500x280 -r 10 frames/image%03d.png # GIF convert -delay 10 -loop 0 frames/*.png source.gif
サウンドを取得し、計画どおりにすべてが見える(そして聞こえる)ことを確認します。
mplayer -ss 0:00:9.73 -endpos 2.86 warlus.webm -ao pcm:file="source.wav" -vo null mplayer -loop 0 -audiofile source.wav source.gif
音声付きのGIFに変換する
python wave2gif.py example/source.gif example/source.wav result.gif
プレイヤーを作る
このプレーヤーは、JavaScriptのアニメーションGIFのプレーヤーであるjsgifに基づいています。 jsgifはgifを解析し、キャンバス上の各フレームの描画を失います。 「RIFFWAVE」ブロックが検出されたときに、それに機能を追加します。
- データをブロックからWAVEファイル形式に変換します。
- 受信したファイルをdata:URLに変換し、Audio要素に転送します。
var doSound = function(sound) { // Header var size = sound.data.length + 4 var size_text = String.fromCharCode(size & 255, (size >> 8) & 255, (size >> 16) & 255, (size >> 24) & 255); var header = [ "RIFF", size_text, // length "WAVE" ].join(''); var out = [header, sound.data].join(''); var dataURI = "data:audio/wav;base64," + escape(window.btoa(out)); sound_element = new Audio(); sound_element.src = dataURI; };
jsgifは速く動作しませんが、音を追加するとさらに遅くなります。 また、ファイルデータを取得するために、プレーヤーはXMLHttpRequestを呼び出します。そのため、プレーヤーは1つのドメインの写真のみを使用します。 しかし、これは芸術への障害です。
次は?
ソース
GIF89a仕様
WAVE PCMサウンドファイル形式
jsgif:JavaScriptのGIFプレーヤー