转码和流式传输到标准输出的 VLC 语法?
VLC syntax to transcode and stream to stdout?
目标: 我正在尝试使用 VLC 作为本地服务器来扩展使用 Adobe AIR
、[=15 创建的应用程序的视频功能=] 和 Actionscript
。我正在使用 VLC
流式传输到 stdout
并从我的应用程序中读取该输出。
VLC Streaming capabilities
VLC Flash Video
Stream VLC to Website with asf and Flash
状态: 我可以启动 VLC
作为后台进程并通过其 remote control interface (more detail 控制它。我可以加载、转码和流式传输本地视频文件。下面的示例应用程序是一个准系统测试平台,演示了这一点。
问题: 我正在将数据导入我的应用程序,但它没有呈现为视频。我不知道这是我的 VLC 命令问题还是从 stdout
写入 to/reading 的问题。这种从 AIR 中的 stdout
读取的技术有效(例如 ffmpeg
)。
我尝试过的各种转码命令之一:
-I rc // remote control interface
-vvv // verbose debuging
--sout // transcode, stream to stdout
"#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=-}"
这会导致数据进入我的应用程序,但由于某些原因,在将 appendBytes
与 NetStream
实例一起使用时,它不会呈现为视频。
如果我将数据写入 .flv 文件,则会创建一个有效文件 – 因此损坏的部分似乎是将其写入 stdout
。 我注意到一件事:我没有通过 stdout` 方法获取元数据。如果我播放使用以下命令创建的文件,我会看到元数据。
// writing to a file
var output:File = File.desktopDirectory.resolvePath("stream.flv");
var outputPath:String = output.nativePath;
"#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=" + outputPath + "}");
希望有人能看到我哪里出错了。
更新 1: 只是为了添加更多细节 (!) – 我查看了生成的 .flv 文件以检查元数据。它出现在文件的头部,如下所示。如果我从磁盘播放文件,我有正确的 onMetaData
处理程序设置并看到此数据的踪迹。 从 stdout
和 NetStream
处于 Data Generation
模式时,我没有看到这个跟踪。 是否有可能它没有被发送到stdout
出于某种原因?我已经尝试生成自己的 header 并在流开始之前附加它 – 我可能没有正确的 header 格式。
更新 2: 所以在我的 AIR
应用程序中,我能够粗略地解析来自 VLC
的传入 stdout
流。我想看看是否正在发送 FLV header 数据——看起来确实如此。我不知道它的格式是否正确等等,但正如我上面提到的,如果我写入 .flv 文件而不是 stdout
,则会创建一个有效的 .flv 文件。
现在完全不知所措 - 已经尝试了我能想到的一切,并跟进了我能找到的每一个网站 link 所涉及的问题。 las – 如此接近,从 AIR
中利用 VLC
会很酷。
更新 3: 根据 VC ONE's
建议,我使用了 his/her 示例代码来检查传入字节的正确数据。我得到一个巨大的字符串(1000 个字符)但这些是第一个:
What I get:
464C560105000000090000000012000111000000000000000200
46 4C 56 01 05 00 00 00 09 00 00 00 00 // check outs
What it should be:
46 4C 56 01 05 00 00 00 09 00 00 00 00
注意:为了让它在 AIR 中工作,您需要将应用程序配置文件定义为 "extendedDesktop"
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="1024" height="768"
showStatusBar="false"
applicationComplete="onApplicationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public var dataIn:Number = 0;
public var dataTotal:Number = 0;
private var processExe:File;
private var processArgs:Vector.<String>;
private var process:NativeProcess;
private var nc:NetConnection;
private var ns:NetStream;
private var vid:Video;
private var videoPath:String; // video to be streamed
protected function onApplicationCompleteHandler(event:FlexEvent):void {
var testFile:File = File.desktopDirectory.resolvePath("test.mp4");
if (testFile.exists){
videoPath = testFile.nativePath;
}
setUpNetStream();
createNativeProcess();
startNativeProcess();
}
protected function setUpNetStream():void {
nc = new NetConnection();
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
nc.addEventListener(NetStatusEvent.NET_STATUS, connStatusHandler);
nc.connect(null);
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
ns.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
var client:Object = new Object();
client.onMetaData = onMetaDataHandler;
ns.client = client;
vid = new Video(640,480);
vid.x= 100;
vid.y = 200;
this.stage.addChild(vid);
vid.attachNetStream(ns);
ns.play(null);
}
private function createNativeProcess():void {
if(NativeProcess.isSupported) {
// This is for OSX;
var pathToVLC:String = "utils/OSX/VLC.app/Contents/MacOS/VLC";
processExe = File.applicationDirectory.resolvePath(pathToVLC);
if (processExe.exists){
process = new NativeProcess();
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
process.addEventListener(ProgressEvent.PROGRESS, onOutputData);
process.addEventListener(ProgressEvent.SOCKET_DATA, onOutputData);
process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
} else {
trace("process not found");
}
} else {
trace("Native Process not supported");
}
}
private function startNativeProcess():void {
processArgs = new Vector.<String>();
processArgs.push("-I rc");
processArgs.push("-vvv"); // verbose debug output
processArgs.push("--sout");
// -------TO WRITE TO A FILE ----------
// file to playback from
//var output:File = File.desktopDirectory.resolvePath("stream.flv");
//var outputPath:String = output.nativePath;
//processArgs.push("#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=" + outputPath + "}");
processArgs.push("#transcode{vcodec=FLV1,acodec=mp3}:gather:std{access=file,mux=flv,dst=-}");
processArgs.push("--sout-keep");
// ------VARIATIONS-------
//processArgs.push("#transcode{vcodec=FLV1,acodec=mp3}:std{access=file,mux=flv,dst=-}");
//processArgs.push("#transcode{vcodec=h264,vb=512,acodec=mp3,ab=128,samplerate=44100}:std{mux=ffmpeg{mux=flv},access=file,dst=-}");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = processExe;
nativeProcessStartupInfo.arguments = processArgs;
process.start(nativeProcessStartupInfo);
// add video to playlist and play
process.standardInput.writeUTFBytes("add " + videoPath + " \n" );
process.standardInput.writeUTFBytes("play" + "\n" );
}
public function onOutputData(event:ProgressEvent):void {
if (process && process.running){
if (process.standardOutput.bytesAvailable){
var videoStream:ByteArray = new ByteArray();
process.standardOutput.readBytes(videoStream,0, process.standardOutput.bytesAvailable);
dataIn = videoStream.length;
dataTotal+= dataIn;
report.text = String("Current Bytes: " + dataIn + "\t Total Bytes: "+ dataTotal);
if (videoStream.length){
ns.appendBytes(videoStream);
}
//trace(ns.info);
}
}
}
private function errorHandler(e:AsyncErrorEvent):void {
trace('ERROR: ' + e.text);
}
private function connStatusHandler(e:NetStatusEvent):void {
trace('CONN_STATUS: ' + e.info.code);
switch(e.info.code){
case "NetConnection.Connect.Success":
//onFinishSetup();
break;
}
}
private function streamStatusHandler(e:NetStatusEvent):void {
trace('STREAM_STATUS: ' + e.info.code);
}
private function streamMetadataHandler(info:Object):void {
for (var key:String in info) {
trace("STREAM_METADATA: " + key + "=" + info[key]);
}
}
public function onErrorData(event:ProgressEvent):void {
if (process && process.running){
trace(process.standardError.readUTFBytes(process.standardError.bytesAvailable));
}
}
public function onIOError(event:IOErrorEvent):void {
trace(event.toString());
}
private function onMetaDataHandler(metadata:Object):void {
trace("### Begin Metadata listing : FLV Entries ### " );
for (var entry:* in metadata)
{
var value:Object = metadata[ entry ];
trace(" > " + entry + " : " + value);
}
trace("### End of Metadata listing for this FLV ### " );
}
]]>
</fx:Script>
<s:Label id="report" x="25" y="25" fontSize="18" />
</s:WindowedApplication>
我会尝试一些事情,其中一些你可能已经想到了:
- 尝试不打开调试,以防弄脏您的标准输出流。
- 如果是特定于格式的问题,请尝试其他视频格式(不是 FLV)。例如,您可以尝试
mpeg4
- 尝试将您的 stdout 流传输到其他东西,例如 ffplay,看看问题出在流上还是您的接收应用对流的假设。
在你的其他问题的评论中,你询问了我的想法:
我注意到在你的代码中你是在 OSX 环境下的 运行 VLC 进程。
在 Windows PC 上请注意 -I rc
稍后不会响应发送的 standardInput
命令。我是 Windows 用户,所以无法帮助解决这部分问题。
尝试使用 --no-rc-fake-tty
甚至 --rc-fake-tty
,VLC 在 PC 上仍然没有响应 stdout
。
您想在 VLC 中进行播放和搜索,但在 AS3 中观看结果(如投影屏幕),对吗?但我什至不确定 VLC 是否会从您选择的时间戳等开始返回 FLV 标签(通过寻找您正在访问特定时间戳的 FLV 标签和相关 a/v 数据)...
其他 FFmpeg/Mencoder 强大的播放器,如我测试过的 MPlayer,仅在播放期间将 "status" 文本数据发送回 stdout
(因此无法馈送到 NetStream
解码器进行显示) .
I was able to crudely parse the incoming stdout
stream coming from
VLC. I wanted to see if the FLV header data was being sent – and it
appears that it is. I don't know if it is in the correct format, etc.
检查字节:(有效的 FLV header 以 46 4C 56 01 05 00 00 00 09 00 00 00 00
开头)
只需使用以下函数的 "bytes check" 结果的 copy-paste 更新您的问题。然后更容易告诉你它是否可以玩,或者你是否需要一些替代品。
1) 设置一些 public(或私有)变量...
- 做一个
public var temp_String : String = "";
- 做一个
public var videoStream:ByteArray = new ByteArray();
2) 用下面的代码替换你的函数 onOutputData
...
public function onOutputData(event:ProgressEvent):void
{
if (process && process.running)
{
if (process.standardOutput.bytesAvailable)
{
//# make a private/public bytearray outside of this function
//var videoStream:ByteArray = new ByteArray();
process.standardOutput.readBytes(videoStream, videoStream.length, process.standardOutput.bytesAvailable);
dataIn = process.standardOutput.bytesAvailable;
dataTotal += dataIn;
//report.text = String("Current Bytes: " + dataIn + "\t Total Bytes: "+ dataTotal);
if (videoStream.length >= 1000 )
{
//ns.appendBytes(videoStream);
temp_String = bytes_toString(videoStream);
trace("bytes checking : " + "\n");
trace( temp_String ); //see hex of FLV bytes
//# temporary pausing of progress events
process.removeEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
}
//trace(ns.info);
}
}
}
支持函数bytes_toString
代码:
public function bytes_toString ( ba:ByteArray ) : String
{
var str_Hex:String = ""; var len:uint = ba.length;
ba.position = 0;
for (var i:uint = 0; i < len; i++)
{
var n:String=ba.readUnsignedByte().toString(16);
if(n.length<2) //padding
{ n="0"+n; } str_Hex += n ;
}
return str_Hex.toUpperCase();
}
一些其他注意事项:
每次触发进度事件一次仅捕获传入 stdout
字节的 32kb / 64kb 数据包。
您将 videoStream:ByteArray = new ByteArray();
设置在 progressEvent 之外,这样每个事件触发都不会生成新的 byteArray(它会丢弃完整的 FLV 标记稍后可能需要的旧数据)。
不要将每个数据包写入 0
位置,因为那样会覆盖现有数据。使用 videoStream.length
作为新的书写位置添加到现有的 end-of。
process.standardOutput.readBytes(videoStream, videoStream.length, process.standardOutput.bytesAvailable);
另外 if (videoStream.length){ ns.appendBytes(videoStream); }
也有点危险。如果您附加得太早,任何不完整的数据(header、帧或其他)都会阻塞 NetStream 解码器。它不会重新启动,除非您重置所有内容并重新开始(re-append 字节的完整 FLV header、完整帧标记等)。
目标: 我正在尝试使用 VLC 作为本地服务器来扩展使用 Adobe AIR
、[=15 创建的应用程序的视频功能=] 和 Actionscript
。我正在使用 VLC
流式传输到 stdout
并从我的应用程序中读取该输出。
VLC Streaming capabilities
VLC Flash Video
Stream VLC to Website with asf and Flash
状态: 我可以启动 VLC
作为后台进程并通过其 remote control interface (more detail 控制它。我可以加载、转码和流式传输本地视频文件。下面的示例应用程序是一个准系统测试平台,演示了这一点。
问题: 我正在将数据导入我的应用程序,但它没有呈现为视频。我不知道这是我的 VLC 命令问题还是从 stdout
写入 to/reading 的问题。这种从 AIR 中的 stdout
读取的技术有效(例如 ffmpeg
)。
我尝试过的各种转码命令之一:
-I rc // remote control interface
-vvv // verbose debuging
--sout // transcode, stream to stdout
"#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=-}"
这会导致数据进入我的应用程序,但由于某些原因,在将 appendBytes
与 NetStream
实例一起使用时,它不会呈现为视频。
如果我将数据写入 .flv 文件,则会创建一个有效文件 – 因此损坏的部分似乎是将其写入 stdout
。 我注意到一件事:我没有通过 stdout` 方法获取元数据。如果我播放使用以下命令创建的文件,我会看到元数据。
// writing to a file
var output:File = File.desktopDirectory.resolvePath("stream.flv");
var outputPath:String = output.nativePath;
"#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=" + outputPath + "}");
希望有人能看到我哪里出错了。
更新 1: 只是为了添加更多细节 (!) – 我查看了生成的 .flv 文件以检查元数据。它出现在文件的头部,如下所示。如果我从磁盘播放文件,我有正确的 onMetaData
处理程序设置并看到此数据的踪迹。 从 stdout
和 NetStream
处于 Data Generation
模式时,我没有看到这个跟踪。 是否有可能它没有被发送到stdout
出于某种原因?我已经尝试生成自己的 header 并在流开始之前附加它 – 我可能没有正确的 header 格式。
更新 2: 所以在我的 AIR
应用程序中,我能够粗略地解析来自 VLC
的传入 stdout
流。我想看看是否正在发送 FLV header 数据——看起来确实如此。我不知道它的格式是否正确等等,但正如我上面提到的,如果我写入 .flv 文件而不是 stdout
,则会创建一个有效的 .flv 文件。
现在完全不知所措 - 已经尝试了我能想到的一切,并跟进了我能找到的每一个网站 link 所涉及的问题。 las – 如此接近,从 AIR
中利用 VLC
会很酷。
更新 3: 根据 VC ONE's
建议,我使用了 his/her 示例代码来检查传入字节的正确数据。我得到一个巨大的字符串(1000 个字符)但这些是第一个:
What I get:
464C560105000000090000000012000111000000000000000200
46 4C 56 01 05 00 00 00 09 00 00 00 00 // check outs
What it should be:
46 4C 56 01 05 00 00 00 09 00 00 00 00
注意:为了让它在 AIR 中工作,您需要将应用程序配置文件定义为 "extendedDesktop"
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="1024" height="768"
showStatusBar="false"
applicationComplete="onApplicationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public var dataIn:Number = 0;
public var dataTotal:Number = 0;
private var processExe:File;
private var processArgs:Vector.<String>;
private var process:NativeProcess;
private var nc:NetConnection;
private var ns:NetStream;
private var vid:Video;
private var videoPath:String; // video to be streamed
protected function onApplicationCompleteHandler(event:FlexEvent):void {
var testFile:File = File.desktopDirectory.resolvePath("test.mp4");
if (testFile.exists){
videoPath = testFile.nativePath;
}
setUpNetStream();
createNativeProcess();
startNativeProcess();
}
protected function setUpNetStream():void {
nc = new NetConnection();
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
nc.addEventListener(NetStatusEvent.NET_STATUS, connStatusHandler);
nc.connect(null);
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler);
ns.addEventListener(NetStatusEvent.NET_STATUS, streamStatusHandler);
var client:Object = new Object();
client.onMetaData = onMetaDataHandler;
ns.client = client;
vid = new Video(640,480);
vid.x= 100;
vid.y = 200;
this.stage.addChild(vid);
vid.attachNetStream(ns);
ns.play(null);
}
private function createNativeProcess():void {
if(NativeProcess.isSupported) {
// This is for OSX;
var pathToVLC:String = "utils/OSX/VLC.app/Contents/MacOS/VLC";
processExe = File.applicationDirectory.resolvePath(pathToVLC);
if (processExe.exists){
process = new NativeProcess();
process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
process.addEventListener(ProgressEvent.PROGRESS, onOutputData);
process.addEventListener(ProgressEvent.SOCKET_DATA, onOutputData);
process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, onIOError);
process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
} else {
trace("process not found");
}
} else {
trace("Native Process not supported");
}
}
private function startNativeProcess():void {
processArgs = new Vector.<String>();
processArgs.push("-I rc");
processArgs.push("-vvv"); // verbose debug output
processArgs.push("--sout");
// -------TO WRITE TO A FILE ----------
// file to playback from
//var output:File = File.desktopDirectory.resolvePath("stream.flv");
//var outputPath:String = output.nativePath;
//processArgs.push("#transcode{vcodec=FLV1}:std{access=file,mux=ffmpeg{mux=flv},dst=" + outputPath + "}");
processArgs.push("#transcode{vcodec=FLV1,acodec=mp3}:gather:std{access=file,mux=flv,dst=-}");
processArgs.push("--sout-keep");
// ------VARIATIONS-------
//processArgs.push("#transcode{vcodec=FLV1,acodec=mp3}:std{access=file,mux=flv,dst=-}");
//processArgs.push("#transcode{vcodec=h264,vb=512,acodec=mp3,ab=128,samplerate=44100}:std{mux=ffmpeg{mux=flv},access=file,dst=-}");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = processExe;
nativeProcessStartupInfo.arguments = processArgs;
process.start(nativeProcessStartupInfo);
// add video to playlist and play
process.standardInput.writeUTFBytes("add " + videoPath + " \n" );
process.standardInput.writeUTFBytes("play" + "\n" );
}
public function onOutputData(event:ProgressEvent):void {
if (process && process.running){
if (process.standardOutput.bytesAvailable){
var videoStream:ByteArray = new ByteArray();
process.standardOutput.readBytes(videoStream,0, process.standardOutput.bytesAvailable);
dataIn = videoStream.length;
dataTotal+= dataIn;
report.text = String("Current Bytes: " + dataIn + "\t Total Bytes: "+ dataTotal);
if (videoStream.length){
ns.appendBytes(videoStream);
}
//trace(ns.info);
}
}
}
private function errorHandler(e:AsyncErrorEvent):void {
trace('ERROR: ' + e.text);
}
private function connStatusHandler(e:NetStatusEvent):void {
trace('CONN_STATUS: ' + e.info.code);
switch(e.info.code){
case "NetConnection.Connect.Success":
//onFinishSetup();
break;
}
}
private function streamStatusHandler(e:NetStatusEvent):void {
trace('STREAM_STATUS: ' + e.info.code);
}
private function streamMetadataHandler(info:Object):void {
for (var key:String in info) {
trace("STREAM_METADATA: " + key + "=" + info[key]);
}
}
public function onErrorData(event:ProgressEvent):void {
if (process && process.running){
trace(process.standardError.readUTFBytes(process.standardError.bytesAvailable));
}
}
public function onIOError(event:IOErrorEvent):void {
trace(event.toString());
}
private function onMetaDataHandler(metadata:Object):void {
trace("### Begin Metadata listing : FLV Entries ### " );
for (var entry:* in metadata)
{
var value:Object = metadata[ entry ];
trace(" > " + entry + " : " + value);
}
trace("### End of Metadata listing for this FLV ### " );
}
]]>
</fx:Script>
<s:Label id="report" x="25" y="25" fontSize="18" />
</s:WindowedApplication>
我会尝试一些事情,其中一些你可能已经想到了:
- 尝试不打开调试,以防弄脏您的标准输出流。
- 如果是特定于格式的问题,请尝试其他视频格式(不是 FLV)。例如,您可以尝试
mpeg4
- 尝试将您的 stdout 流传输到其他东西,例如 ffplay,看看问题出在流上还是您的接收应用对流的假设。
在你的其他问题的评论中,你询问了我的想法:
我注意到在你的代码中你是在 OSX 环境下的 运行 VLC 进程。
在 Windows PC 上请注意 -I rc
稍后不会响应发送的 standardInput
命令。我是 Windows 用户,所以无法帮助解决这部分问题。
尝试使用 --no-rc-fake-tty
甚至 --rc-fake-tty
,VLC 在 PC 上仍然没有响应 stdout
。
您想在 VLC 中进行播放和搜索,但在 AS3 中观看结果(如投影屏幕),对吗?但我什至不确定 VLC 是否会从您选择的时间戳等开始返回 FLV 标签(通过寻找您正在访问特定时间戳的 FLV 标签和相关 a/v 数据)...
其他 FFmpeg/Mencoder 强大的播放器,如我测试过的 MPlayer,仅在播放期间将 "status" 文本数据发送回 stdout
(因此无法馈送到 NetStream
解码器进行显示) .
I was able to crudely parse the incoming
stdout
stream coming from VLC. I wanted to see if the FLV header data was being sent – and it appears that it is. I don't know if it is in the correct format, etc.
检查字节:(有效的 FLV header 以 46 4C 56 01 05 00 00 00 09 00 00 00 00
开头)
只需使用以下函数的 "bytes check" 结果的 copy-paste 更新您的问题。然后更容易告诉你它是否可以玩,或者你是否需要一些替代品。
1) 设置一些 public(或私有)变量...
- 做一个
public var temp_String : String = "";
- 做一个
public var videoStream:ByteArray = new ByteArray();
2) 用下面的代码替换你的函数 onOutputData
...
public function onOutputData(event:ProgressEvent):void
{
if (process && process.running)
{
if (process.standardOutput.bytesAvailable)
{
//# make a private/public bytearray outside of this function
//var videoStream:ByteArray = new ByteArray();
process.standardOutput.readBytes(videoStream, videoStream.length, process.standardOutput.bytesAvailable);
dataIn = process.standardOutput.bytesAvailable;
dataTotal += dataIn;
//report.text = String("Current Bytes: " + dataIn + "\t Total Bytes: "+ dataTotal);
if (videoStream.length >= 1000 )
{
//ns.appendBytes(videoStream);
temp_String = bytes_toString(videoStream);
trace("bytes checking : " + "\n");
trace( temp_String ); //see hex of FLV bytes
//# temporary pausing of progress events
process.removeEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);
}
//trace(ns.info);
}
}
}
支持函数bytes_toString
代码:
public function bytes_toString ( ba:ByteArray ) : String
{
var str_Hex:String = ""; var len:uint = ba.length;
ba.position = 0;
for (var i:uint = 0; i < len; i++)
{
var n:String=ba.readUnsignedByte().toString(16);
if(n.length<2) //padding
{ n="0"+n; } str_Hex += n ;
}
return str_Hex.toUpperCase();
}
一些其他注意事项:
每次触发进度事件一次仅捕获传入 stdout
字节的 32kb / 64kb 数据包。
您将 videoStream:ByteArray = new ByteArray();
设置在 progressEvent 之外,这样每个事件触发都不会生成新的 byteArray(它会丢弃完整的 FLV 标记稍后可能需要的旧数据)。
不要将每个数据包写入 0
位置,因为那样会覆盖现有数据。使用 videoStream.length
作为新的书写位置添加到现有的 end-of。
process.standardOutput.readBytes(videoStream, videoStream.length, process.standardOutput.bytesAvailable);
另外 if (videoStream.length){ ns.appendBytes(videoStream); }
也有点危险。如果您附加得太早,任何不完整的数据(header、帧或其他)都会阻塞 NetStream 解码器。它不会重新启动,除非您重置所有内容并重新开始(re-append 字节的完整 FLV header、完整帧标记等)。