うつ日記 ~うつを克服するための日記~

うつ病のため休職してから復帰するための体験、工夫、Androidアプリの紹介、アプリの作成ノウハウなど。アプリはこちら→ https://play.google.com/store/apps/details?id=tokin_kame.utunikki_app

AVCHD(.MTSファイル)から日時字幕入りのDVDを作成する。

はじめに

記録としてビデオカメラで撮影した動画を、DVDにして残したりする場合、撮影した日時も残したいんだけど、単純には出来なくて、苦労したので、方法をまとめておきます。
ちなみに、DVテープの頃は、WindowsならArea61 DVビデオタイマ、Linuxならkinoというソフトを使えば動画に日時を埋め込むことができました。
MTS(AVCHD)ファイルでも、一旦DV形式やAVI形式に変換して、同じ方法を使うという事も考えられますが、MTSファイルから変換したデータには、DVテープから取り出したデータのように日時情報が入っていないらしく、うまくいきませんでした。

それで、MTSファイルに残っている時間情報を利用して、字幕を付ける手順をまとめます。

 

○手順

今回は、日時の情報を字幕としてDVDに入れることにしました。
色々試した結果、Linuxフリーソフトだけでできるようになりました。
全体の流れは以下の通りです。

 ①MTSファイルをビデオカメラからパソコンへコピーする
 ②perlスクリプトにより、字幕ファイル(srt形式)を作成する
 ③catコマンドで、動画ファイルを連結する
 ④DeVeDeを使って、字幕入りのVOBファイルを作成する

LinuxUbuntu 14.04を使用しました。

 

○事前準備

「Image::ExifTool」というライブラリをインストールすることで、perlでMTSファイルから日時情報を取得することが、できるようになります。
Ubuntuの場合は、Ubuntuソフトウェアセンターで、「Image::ExifTool」と入力して検索すると、「libimage-exiftool-perl」というのがヒットするので、これをインストールすると使えるようになります。
 

○字幕ファイルの作成

・srt形式について

字幕ファイルには、いくつか種類があるようだが、srt形式ならテキストファイルなので、perlで作成することができます。
srt形式では、以下のように字幕を記述するらしいです。

最初に、字幕の通し番号
次の行に、字幕を表示させる時間(開始時間 --> 終了時間)
更に次の行に、表示させる内容

例えば、以下のように書くと、最初から1秒間「2012/06/03 16:12:12」という字幕を表示する。

1
00:00:00,000 --> 00:00:01,000
2012/06/03 16:12:12

これを、1単位として、改行を入れて、繰り返せば指定した時間で字幕を入れ替えることができます。
日時を1秒単位で表示したい場合には、上記のセットを1秒単位で作成すれば良いことになります。

 

perlスクリプト

以下に、今回作成した字幕ファイルを作成するスクリプトを示します。

#!/usr/bin/perl

use Image::ExifTool qw(:Public);

$dirname = "63/STREAM";

opendir(DIR, $dirname);
@file_tmp = readdir(DIR);
closedir(DIR);
@file = sort(@file_tmp);
$count_all = 1;
$ins_time1 = "00:00:00";
#$ins_time2 = "00:00:01";
$ins_time2 = "00:00:05";
$i = 0;
foreach $file(@file){
	if($file =~ /[0-9]+.MTS/){

		$info = ImageInfo("$dirname/$file");
		$DateTimeOriginal = $info->{'DateTimeOriginal'};
		$FileModifyDate = $info->{'FileModifyDate'};

		$end_time = &count_time($DateTimeOriginal, $FileModifyDate);
		if($i == 0){
				$end_time -= 35;
		}
		for($count = 0; $count < $end_time; $count += 5){
			$print_time = &print_time($DateTimeOriginal, $count);

			print "$count_all\n$ins_time1,001 --> $ins_time2,000\n                                                          $print_time\n\n";
			$ins_time1 = &ins_time($ins_time1);
			$ins_time2 = &ins_time($ins_time1);
			$count_all++;
		}
		$i++;
	}

}

sub count_time{
	my $start_time = $_[0];
	my $end_time = $_[1];
	my $year;
	my $month;
	my $date1;
	my $date2;
	my $time;
	my $minute;
	my $sec;
	my $output;
	my $start_time_2;
	my $end_time_2;

	if($start_time =~ /([0-9]+):([0-9]+):([0-9]+) ([0-9]+):([0-9]+):([0-9]+)\+/){
		$year = $1;
		$month = $2;
		$date1 = $3;
		$time = $4;
		$minute = $5;
		$sec = $6;

		$start_time_2 = ($time * 60 + $minute) * 60 + $sec;
	}
	if($end_time =~ /([0-9]+):([0-9]+):([0-9]+) ([0-9]+):([0-9]+):([0-9]+)\+/){
		$date2 = $3;
		$time = $4;
		$minute = $5;
		$sec = $6;

		$end_time_2 = ($time * 60 + $minute) * 60 + $sec;
	}
	$output = $end_time_2 - $start_time_2;
	if($date1 != $date2){
		$output += 24 * 60 * 60;
	}
	return($output);
}

sub print_time{
	my $start_time = $_[0];
	my $count = $_[1];
	my $month;
	my $date1;
	my $date2;
	my $time;
	my $minute;
	my $sec;
	my $output;

	if($start_time =~ /([0-9]+):([0-9]+):([0-9]+) ([0-9]+):([0-9]+):([0-9]+)/){
		$year = $1;
		$month = $2;
		$date = $3;
		$time = $4;
		$minute = $5;
		$sec = $6;

		$sec += $count;
		while($sec >= 60){
			$sec -= 60;
			$minute++;
		}
		while($minute >= 60){
			$minute -= 60;
			$time++;
		}
		while($time >= 24){
			$time -= 24;
			$date++;
		}
	}
		if($sec =~ /[0-9][0-9][0-9]/){
		print "err:$sec\n";
		exit;
	}
	#秒単位
	$output = sprintf("%d/%02d/%02d\n                                                                    %02d:%02d", $year, $month, $date, $time, $minute);
	return($output);
}

sub ins_time{
	my $ins_time = $_[0];
	my $time;
	my $minute;
	my $sec;
	my $output;

	if($ins_time =~ /([0-9]+):([0-9]+):([0-9]+)/){
		$time = $1;
		$minute = $2;
		$sec = $3;

		$sec += 5;
		if($sec >= 60){
			$sec -= 60;
			$minute++;
		}

		if($minute >= 60){
			$minute -= 60;
			$time++;
		}
	}

	$output = sprintf("%02d:%02d:%02d", $time, $minute, $sec);
	return($output);
}

 

perlスクリプトの使い方

まず、上記のスクリプトをファイルに保存します。
改行コードは「lf」にしておきます。
$dirnameにMTSファイルが置いてあるディレクトリを指定します。
以下のように書いた場合には、「52/STREAM」というディレクトリの下にあるMTSファイルを探して、そのファイルの情報を取得します。

$dirname = "52/STREAM";

字幕の情報は、標準出力に吐き出すので、例えば、スクリプトを「make_srt.pl」という名前で保存して、「test.srt」という名前の字幕ファイルを作成する場合には、以下のようにしてファイルに保存します。

perl make_srt.pl > test.srt

 

catコマンドで、動画ファイルを連結する

MTSファイルが複数ある場合、1つ1つに対して、srtファイルを作成して、設定しても良いですが、ファイル数が多いと設定がめんどくさいので、1つにまとめてから扱うことにしました。

MTSファイルといえど、連結は簡単で、Linuxのコマンドで、以下のような感じでできます。

cat 52/STREAM/*.MTS > 52.MTS

 

○DeVeDeで字幕ファイルとして読み込む

作成したsrtファイルとMTSファイルを組み合わせてDVDを作成します。

DeVeDeを開いて、右側の方のプロパティをクリックします。

f:id:tokin_kame:20150531133516p:plain

すると、以下のようなウインドゥが開きます。

f:id:tokin_kame:20150531133609p:plain

 ここで、一番上のFileのところにMTSファイルを指定します。

次に、真ん中より下の辺りのSubtitlesのところに作成したsrtファイルを指定します。

後は普通に作成すれば、撮影日時が字幕として入ったDVDが完成します。

デフォルトで字幕を表示させるかどうかも、DeVeDeで設定できたと思います。

 

○残っている課題

一応、日時字幕入りのDVDを作成することはできますが、以下のような課題が残っています。
・字幕のズレ

今回作成したDVDでは、動画の場面の切り替わりから、1〜4秒程度字幕の切り替わりが遅れるという現象が見られました。

字幕の秒単位なのに対して、動画はもっと細かい単位で切り替わるので、ズレが生じるのかもしれません。

今回できたのを見る限りでは、ズレは累積はしていない様なので、大きな問題ではないかという事にしましたが、まだ改良の余地が有ると思われます。

 

 

 

 

うつ日記 ~うつを克服するための日記~
https://play.google.com/store/apps/details?id=tokin_kame.utunikki_app