バラバラのファイルを結合してみる

 ライブラリを見ていると、手持ちのビデオファイルのいくつかで気になるものがあった。ようするにいくつかのファイルに分断されてしまっているもので、多くは当時持っていたデバイスが大容量に耐えられず、小さくわけていたものだと思われる。

 ファイル形式は適当なツールがあればどうにでも変更できる。

 だが、今の時代にあわせて元通り結合したい。もうオリジナルを持っていないソースも多いのだし。ではさっそくはじめよう。

catで結合してみる。

 あなたがLinux使いなら、ファイル形式によってはcatコマンドでぱぱーっと結合できる。これが一番簡単。試しにやってみよう。

 だが cat コマンドで接合できるファイル形式は限られるので、まずこれに変更する。うちは手軽なところで ffmpeg を使ったけど、そこは好きなツールでやってほしい。

File a

Leda-1.mp4
Leda-2.mp4
Leda-3.mp4
  :
  :
Leda-12.mp4

File b

#!/bin/sh
B=""
for i in `cat a`;do
  A=`echo $i|sed s/.mp4$/.mpg/g`
  echo $i $A
  B="$B $A"
  ffmpeg -sameq -i "$i" "$A"
done
cat $B > Leda.mpg
echo "#.. Last Regret!"
ffmpeg -i Leda.mpg -sameq Leda.mp4

実行

$ sh b

結果

 ばっちりできたが、これはこれで問題が起きた。 美しくない のだ ^^; なんちゅーか激しく汚い。

 わかる人は拡張子のmpgでわかると思うが、 一度 mpeg-1 に変換するんだから美しくないのはむしろ当たり前 なのだ。

 そもそもデジタルの原理とは、映像をデジタル値に変換したもの。それをどう圧縮するかというと刹那ごとの差分を時系列でとり、クロマキー合成のように差分をつきあわせると思えばいい(厳密にはそこまで簡単ではないはずだが)。だからこそ場面チェンジの一瞬などは差分が大きくいわけで環境によって画像が乱れる事があるのだが、それ以前に構造上、どうしても古いタイプは荒く余計に画像が毛羽立ち汚い。

 というわけでデータ形式を変えずにくっつける事にする。

mencoderで結合してみる。

 さて、別の方法としては mencoder を使うやり方がある。これは mplayer という汎用メディアプレイヤーに付属しているものだ。(最近のLinuxシステムなどではパッケージが別になっているが)

 論より証拠、やってみよう。

#!/bin/sh
B=""
for i in `cat a`;do
  B="$B $i"
done
mencoder $B -o Leda-3.mp4 -oac copy -ovc copy

 mencoderのコマンドの意味を簡単に説明する。

パラメータ 意味
-o ファイル名 結果はこの名前で出力する。
-oac copy (Option of Audio Codec is "copy") オーディオのデータ形式を変えず複写。
-ovc copy (Option of Video Codec is "copy") ビデオ(同上)

 うちではこんな感じで走らせるわけだが……実際に走るコマンドはこうなる。

$ mencoder Leda-1.mp4 Leda-2.mp4 ... Leda-12.mp4 -o Leda.mp4 -oac copy -ovc copy

 おや?何か文句を言われたようだ。

Audio format 0x4134504d is incompatible with '-oac copy', please try '-oac pcm' instead or use '-fafmttag' to override it.

 うげ。と、とりあえず頑張って拾い読む。

 うーむ。ようするに「Audio format なんちゃらは "-oac copy" 形式でうまく処理できない。"-oac pcm" で代用する(instead)か、上書き用に "-fafmttag" を試してみてほしい」ってとこかな?

 ちなみにPCMという表現で想像つくと思うが -oac pcm というのは 非圧縮で収納しろ って事。確かにベタ打ちにしちゃえば無問題だからね。サイズが大きくなってしまうが、なに、後でもう一度オーディオのみ圧縮すればいい。これは ffmpeg でやるとして、今は非圧縮で走らせよう。

$ mencoder Leda-1.mp4 Leda-2.mp4 ... Leda-12.mp4 -o Leda.mp4 -oac pcm -ovc copy

 よし、これでOK。

別の事例(Yet Another Errors)

 ちなみになんだが「一見すると正しく終わるようだけど途中で切れてる」という事象も別の動画で発生した。こういう時は mencoder の実行結果を見るのだが……たとえば以下のメッセージをみつけた。もしあなたのケースで起きたら参考にしてほしい。

:
:
==========================================================================
videocodec: framecopy (480x320 24bpp fourcc=34363248)
videocodec: framecopy (480x320 24bpp fourcc=34363248)

All video files must have identical fps, resolution, and codec for -ovc copy.

Exiting...
$

 お?なんかあったぞ。

 ふむふむ。「-ovc copyするためには、すべてのビデオはfps、解像度、コーデックが一緒じゃないとダメだよー」だそうである。なるほど、違うやつが混じってたのでそこで中断してしまったのね。

 ならば仕方ない。copyでなく形式を指定しよう。再エンコになるので時間かかるけどな。

$ mencoder FT.mp4 FT-2.mp4 ... FT-5.mp4 -o FT.mp4 -oac pcm -ovc x264

 これでよし。

仕上げ(ffmpeg)

 このままでも再生には問題ないが、オーディオが非圧縮なので異様に大きくなってしまう。たぶん「げ、なんだこりゃ」と驚くと思う。

 せっかくだから今度こそ ffmpeg を使う。オーディオのみ圧縮するのは実に簡単。

$ ffmpeg -i Leda.mp4 -vcodec copy Leda-2.mp4
パラメータ 意味
-i ファイル名 変換元ファイル名
-vcodec copy Video Codecをcopyで(変更しない)

Audio Codecの指定がないがこれでOK。論より証拠は以下。

Seems stream 0 codec frame rate differs from container frame rate: 30000.00 (30000/1) -> 29.97 (30000/1001)
Input #0, avi, from 'Leda.mp4':
  Metadata:
    encoder         : MEncoder git-ab94fc6-4.4.3
  Duration: 01:09:45.94, start: 0.000000, bitrate: 1622 kb/s
    Stream #0.0: Video: mpeg4, yuv420p, 320x240 [PAR 1:1 DAR 4:3], 29.97 fps, 29.97 tbr, 29.97 tbn, 30k tbc
    Stream #0.1: Audio: pcm_s16le, 44100 Hz, 2 channels, s16, 1411 kb/s
Output #0, mp4, to 'Leda-2.mp4':
  Metadata:
    encoder         : Lavf52.87.1
    Stream #0.0: Video: mpeg4, yuv420p, 320x240 [PAR 1:1 DAR 4:3], q=2-31, 30k tbn, 29.97 tbc
    Stream #0.1: Audio: libfaac, 44100 Hz, 2 channels, s16, 64 kb/s
Stream mapping:
  Stream #0.0 -> #0.0
  Stream #0.1 -> #0.1

 よく見るとわかると思うが、元ファイルの音声が「pcm_s16le」になっていると思う。私も詳しくは知らないがたぶん、非圧縮PCM16ビット、ベタ打ちくらいの意味と思われる(ぉぃぉぃ

 んで、出力先は、何も指定してないのに mpeg4 aac 16ビット 44100Hzになっている。

 これはどういう事かというと、mpeg4として無難なとこを選んで圧縮してくれたというわけだ。もちろんここでそのまま通して欲しいなら、 -acodec copy とすればいいわけだがむしろ今回は圧縮して欲しいわけなので、そのまま通せばよい。

動画の横のデータ形式に注目。ちゃんと圧縮されてますね?

以上