結論から言います。
アクトビラ対応機器のブラウザで好きな動画が楽しめます。
もうDLNA対応機やREGZA厨と喧嘩しなくていいんですね。朗報
ただし、イバラの道なので初心者にはお勧めしません。うまく動作するテレビやSTBならとても快適です。
今回実験に使ったBuffaloの機器だと余裕でした。
その他メーカの場合は、コーデックが難しい、誰か実験を助けてください。
アクトビラで再生する動画の作り方
ffmpeg -y -i 2355.mp4 -vcodec libx264 -acodec copy test2.m2ts
ポイントは、拡張子 m2ts これが188バイトのヘッダにタイムスタンプを入れた192バイトのヘッダをつけた、タイムスタンプ付きTSを作るための魔法の拡張子。本当はArib仕様を読み解いて作りたいけどね。
アクトビラのブラウザに配信する方法
- アクトビラ対応TVにアドレス入力出来る場所にHTMLを置く
- HTMLが見られることを確認する。
- CPCファイルを設置する
- CPCファイルへのリンクを作る
- TVでCPCファイルをクリックする
- 動画の再生が始まる。
(CA3G0443)
CPCファイルの動画部分にURLを指定
<startup>
<content_title>test</content_title>
<duration>000000</duration>
<start>http://192.168.2.5/0655_HD.m2ts</start>
</startup>
ここの部分の動画いm2tsを指定しました。
あとはindex.htmlで
さっき作ったCPCファイルをリンク先に指定します。
<a href="http://192.168.2.5/test.cpc?LID=none&Return=http://192.168.2.5/">0655_HD@atom </a><
と指定します。
LIDは課金用決済のセッションコード、Returnは再生終了後に開くブラウザに渡すアドレス。
URLを入力して
(CA3G0444)
(CA3G0445)
クリック
(CA3G0446)
すると再生が始まる。
(CA3G0447)
おおおお!やりましたね。
(CA3G0448)
ニコ動を変換したTSがAQUOSブラウザで再生されました。やったね。
これでテレビのリモコンで動画が見られるようになります。
マウスで操作したりDLNAで探すのは面倒でした。HTMLで表示できるので便利ですね。役得。
AQUOSでもなんとか頑張ってPT2のTSも見れるようになるんです。
さて、こういう仕様は何処で調べるのか。
デジタルテレビ情報化研究会/発行物
個々にかいてあるPDFが置いてありました。PDFを詳細に読み進めればわかるんだけど。如何せん面倒くさい。
CPCファイルについて
CPCファイルについては、デジタルテレビ ネットワーク機能仕様-ストリーミング機能仕様書-プロトコル編(v1.1)
に記述されているんですが。。。。これが結構ややこしい。でもCPCファイルがキモなので必須ですね。
3パートから構成される「CPC」
CPCファイルは3パートから構成されます。
Content-Type:application/X-arib-resourceList
Content-Location:FL-NOENC.eri
Content-Location:RTP.nci
の3パートです。
(スクリーンショット 2012-03-02 5.21.40)
それぞれ役割があって
- arib-resourceList
- ここにはFL-NOENC.eriとRTP.nciを見に行けと、バイナリで書いてある。(これが面倒でね、、)
- FL-NOENC.eri
- ここには、動画ファイルのURLとコーデックや長さとかがXMLで 記述されてる
- RTP.nci
- ここには、ファイルのプロトコルが書いてある(固定)
このほかに、課金情報とかあるらしいんだけど、調べても使ってる人居ないみたい。
形式はHTTPヘッダ形式とかMIME形式とか規格書に書いてある。まぁ、MHTMLやマルチパートのメールと同じです。通常のMIMEです。
CPCの欠点
CPCには"Content-Type:application/X-arib-resourceList"があるんだけど、これがめんどくさい仕様なんですよ。
これが先頭のフォーマット形式
(スクリーンショット 2012-03-02 5.20.20)
先頭パートとには「このCPCは3つのパートからなる」と書いてある。
先頭パートのバイナリ・フォーマットの定義リスト
(Aribによる定義)
つまり、バイナリなんですね。先頭行からちょこちょこ読めばいいんです。でもね、バイナリがBase64されてないので、コピペが激しく難しい。これがアクトビラの解析で一番の罠っぽい感じです。
であとは、Content-Lengthに気をつけながらファイルを書く。
CPCファイルはかなり厳格に読まれる。なぜかというとだ、arib-resourceListがバイナリだから、長さが結構重要みたい。適当に書き換えたら動かない。そのくせタグの中は全く見てなくて、「MPEGだぜESはMPE2だぜ」とCPCに書いてH.264/AVCを送信しても読んじゃいます。
CPCファイルをContent-Lengthにさえ注意して作れば完成です。
CPCファイルさえ作ればあとは簡単よ。
一応AQUOSでもいけることは確認した。タイムスタンプ付きTSを作るだけ。
リモコン操作で簡単動画
epgrecとかだとブラウザ経由で見れるので、正直パソコン触るのが面倒なのでリモコン解決は嬉しい感じ。
大事な事は、アクトビラ対応のテレビにTS直接配信できるということ
ここが重要。しかもHTMLで記述できるからDLNAより楽かも知んない。
*1
早送りとスキップかはどうするの
このエントリのブクマが伸びたらまた続編書きます。そんときにでも。
生産完了になってる。いそげ
ヤフオクで安くで手に入るしいまならいける。
手伝ってください。
CPCファイルの解析は済んだのです、いまはCPCファイルのジェネレーターを作るところです。しかし我が家にはAQUOSしかないので、他メーカのブラウザでも試してみたいんですが。協力してもらえませんか。
アクトビラってガラパゴス化の最たるものだと思うけど。HTMLを意識した標準化を頑張ってる。そのへんか好感が持てる。でも情報リソースが少なくて秘密主義でもっとオープンになってもいいと思う。喧伝が下手だ。
CPCのresource.bin の解析コード
2014-04-06追加。解析コード書いておいた。
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void){
uint8_t num_of_resources;
uint8_t resourceInfoLength;
int32_t resourceOffset;
uint16_t headerLength;
uint32_t resourceLength;
uint16_t resourceTypeValue;
int8_t resourceNameLength;
FILE *fp;
fp = fopen("res.info", "rb");
if( fp==NULL ){
printf("fopen Error.\n");
return 1;
}
fread(&num_of_resources, 1 , 1 , fp);
printf( "num_of_resources = %d \n", num_of_resources);
for(int i =0;i<num_of_resources;i++){
printf( "{ \n");
fread(&resourceInfoLength, 1 , 1 , fp);
fread(&resourceOffset , 4 , 1 , fp);
fread(&headerLength , 2 , 1 , fp);
fread(&resourceLength , 4 , 1 , fp);
fread(&resourceTypeValue , 2 , 1 , fp);
fread(&resourceNameLength, 1 , 1 , fp);
printf( "resourceInfoLength = %d \n", resourceInfoLength);
printf( "resourceOffset = %d \n", resourceOffset);
printf( "headerLength = %d \n", headerLength);
printf( "resourceLength = %d \n", resourceLength);
printf( "resource:TypeValue = 0x%04x \n", (resourceTypeValue & 0xF000) );
printf( "resource:SubTypeValue = 0x%04x \n", (resourceTypeValue & 0x0FFF ));
printf( "resourceNameLength = %d \n", resourceNameLength);
printf( "resourceName = ");
for(int j=0;j<resourceNameLength;j++){
printf("%c", fgetc(fp));
}
printf("\n");
printf( "} \n");
}
fclose(fp);
return 0;
}