顯示具有 FLV 標籤的文章。 顯示所有文章
顯示具有 FLV 標籤的文章。 顯示所有文章

2010-02-22

Video 保護

目前 FLV 的保護主要由 FMS 下手, 但是用 FMS 有諸多缺點。
Adobe AIR 2 將提供 DRM 的功能, 但是需搭配 Flash Access 2 使用。依據之前的經驗, Flash Access 2 應該不會便宜到哪去, 而且 Video 的傳輸頻寬也是問題。

在簡單保護方面(防外行), NetConnection 和 NetStream 實在包的太「好」了, 沒有下手的空隙。如果使用 AIR 2, 可以用 ServerSocket 弄個 HTTP Server 來傳 Video 資料。這個時候, Video 就可以編碼(隨君高興)存成檔案, 在 Server 讀資料送出時, 可以自行解碼, 再送給 Client。這樣做的缺點是效能會略差, 而且要想辦法藏好解碼的 KEY(可以透過登入機制再拐個彎, 有心要找的人還是可以找到)。

2007-08-02

lighttpd Web Server

號稱跟 apache httpd 相比, 可處理更多的連線的 web server
官網: lighttpd fly light
在 windows 上跑的專案: WLMP Project
支援 flv streaming

2007-07-04

Mapping Flash video to 3D objects

Adobe 官方的教學, 將影片貼在 3D 的物件上, 使用 Papervision 3D library。

2007-06-28

取得 FLV 內的 header 資料

依據 osFlash 裡 FLV 檔案資料格式的說明, 利用 Flash 開發「取得 FLV 檔頭資料及串流資料」的 AIR app。
要注意的是 meta 裡包含兩個 AMF packets, 所以需使用 ByteArray.readObject() 兩次。
Flash frame AS3:
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

var file:File;
var fs:FileStream;
var flvFilter:FileFilter = new FileFilter("Flash Video", "*.flv");
var header_ba:ByteArray;
var stream_ba:ByteArray;

function bClick(e:MouseEvent):void {
var targetName:String = e.target.name;
switch (targetName) {
case "open_btn" :
file = new File();
file.browseForOpen("Open", [flvFilter]);
file.addEventListener(Event.SELECT, readFLVHeader);
break;
case "show_btn" :
readStreamHeader();
break;
case "close_btn" :
fs.close();
break;
}
}
open_btn.addEventListener(MouseEvent.CLICK, bClick);
show_btn.addEventListener(MouseEvent.CLICK, bClick);
close_btn.addEventListener(MouseEvent.CLICK, bClick);


function readFLVHeader(e:Event) {
filename_txt.text = file.nativePath;
fs = new FileStream();
fs.open(file, FileMode.READ);

// read FLV Header
header_ba = new ByteArray();
fs.readBytes(header_ba, 0, 9);
main_txt.text = "Signature: "+ header_ba.readMultiByte(3, "") +"\n";
main_txt.appendText("Version: "+ header_ba.readUnsignedByte()+"\n");
main_txt.appendText("Flags: "+ header_ba.readUnsignedByte()+"\n");
main_txt.appendText("Offset: "+ header_ba.readUnsignedInt()+"\n");
main_txt.appendText("---\n");
}
function readStreamHeader() {
stream_ba = new ByteArray();
fs.readBytes(stream_ba, 0, 15);

main_txt.appendText("PreviousTagSize: "+ stream_ba.readInt()+" ----\n");
var type:uint = stream_ba.readUnsignedByte();
main_txt.appendText("Type: "+ type +"\n");
// 取 3 bytes
var bodyLength:uint = stream_ba.readUnsignedShort()<<8 | stream_ba.readUnsignedByte();
main_txt.appendText("BodyLength: "+ bodyLength +"\n");
var timestamp:uint = stream_ba.readUnsignedShort()<<8 | stream_ba.readUnsignedByte();
main_txt.appendText("Timestamp: "+ timestamp +"\n");
main_txt.appendText("Padding: "+ stream_ba.readUnsignedInt()+"\n");
if (type == 0x12) {
var t_ba:ByteArray = new ByteArray();
fs.readBytes(t_ba, 0, bodyLength);
// 設定 AMF 的格式, 即使是 on2 VP6 應該還是舊的
t_ba.objectEncoding = ObjectEncoding.AMF0;
// 第一個 AMF 物件是事件處理器的資料
var obj:Object = t_ba.readObject();
var str:String = QopDump.go( obj );
main_txt.appendText("***\nEvent handler:"+str+"\n***\n");
obj = t_ba.readObject();
str = QopDump.go( obj );
main_txt.appendText(str+"\n");
} else {
// skip the body
fs.position += bodyLength;
}
main_txt.verticalScrollPosition = main_txt.maxVerticalScrollPosition;
}

FLV 的第一個 stream unit 應該都是 meta。較舊 FLV 的 meta 大多有問題, 沒有提供仔細而實用的資料。

較新格式的 FLV 其 Flags 通常是 13 而不是 5。


原始檔: parseFLV.fla
安裝檔: parseFLV.air

FB 留言