- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在AS3中遇到NetStream的问题。我正在从事的项目允许用户浏览视频(本地)并播放。我遇到的问题是,尽管我进入NetStatusEvent函数并触发了netStream.seek(0);
,但据我所知NetStream.Seek.Notify
并没有任何作用。我正在使用NativeProcess,以下功能对此没有任何影响。
public function ProgressEventOutputHandler(e:ProgressEvent):void {
videoByteArray = new ByteArray();
nativeProcess.standardOutput.readBytes(videoByteArray, 0, nativeProcess.standardOutput.bytesAvailable);
netStream.appendBytes(videoByteArray);
}
netStream.seek(0);
之前暂停了netStream。
videoByteArray = new ByteArray();
移到我的init函数中,并且还在此函数中创建了
tempVideoByteArray = new ByteArray();
。
nativeProcess.standardOutput.readBytes(videoByteArray, videoByteArray.length, nativeProcess.standardOutput.bytesAvailable);
最佳答案
精简版 :
试试我粘贴在这里的代码:Github Snippet链接
长版:
这个有点长,但希望它能一劳永逸...不用担心砖墙上的东西,墙壁被打碎了。为了激发您的灵感,请查看VC:One实验室使用appendBytes
进行的内部演示:
MP4 Seeking Experiment:研究appendBytes
帧数据访问和时间/搜索处理。实时帧字节仅使用AS3代码从MP4转换为FLV格式。
Speed Adjust of Audio & Video:用于视频分离和效果实验中的实时MP3音频。需要MP4 / FLV文件以及音频轨道中的MP3数据。
Synchronised Video Frames:用于以相同帧号显示的多个视频。
PS:我将使用URLStream
方法,因为这对于加载本地文件或在线文件的人来说是一个更有用的答案。您可以从urlstream.progressEvent
更改为通常的nativeProcess.progressEvent
。
我知道FFMPEG,但只使用AIR制作了Android应用。因此,对于这种AIR / FFMPEG连接,您比我了解的更多。
另外,此答案还假设您正在将FLV与MPEG H.264视频和MP3或AAC音频一起使用。ffmpeg -i input.mp4 -c:v copy -c:a mp3 -b:a 128k -ac 2 -ar 44100 FLV_with_MP3.flv
这个假设很重要,因为它会影响我们要寻找的字节类型。
对于以上带有H.264视频和AAC或MP3音频的FLV,我们可以期望以下内容(在搜索时):
由于这是MPEG,因此第一个视频标签将保留AVC解码器配置字节,而第一个音频标签将保留“音频特定配置”字节。此数据不是实际的媒体帧,只是像音频/视频标签一样打包。 MPEG回放需要这些。可以在MP4容器内的STSD
元数据条目(MOOV
原子)中找到相同的字节。现在,下一个找到的视频标签将(或应该)是视频的实际第一帧。
视频关键帧:从0x09开始,下一个第11个字节为0x17,第12个字节为0x01
音频TAG AAC:从0x08开始,下一个11个字节为0xAF,第12个字节为0x01
音频TAG MP3:从0x08开始,下一个第11个字节为0x2F,第12个字节为0xFF
1)字节复制和检查值:
您正在寻找代表视频“标签”的字节。除了元数据标签外,您现在可以期望“标签”表示音频或视频帧的容器。有两种方法可以将标记字节放入“临时字节数组”中(我们将其命名为temp_BA
)。ReadBytes
(慢):提取source_BA
的开始/结束范围内的各个字节值WriteBytes
(快速):立即复制source_BA
中字节的开始/结束范围
Readbytes解释:告诉Source将其字节读入Target。源将从其当前偏移量(位置)开始向前读取直至其长度。继续阅读之前正确的源位置...source_BA.readBytes( into Target_BA, Pos within Target_BA, length of bytes required );
执行完上述行后,“源”位置现在将向前移动以说明新的行进长度。 (公式:源新Pos = previousPos + BytesLengthRequired)。
Writebytes解释:告诉Target从Source复制一定范围的字节。自从已知信息(从源)复制以来,速度很快。目标从当前位置开始写...target_BA.writeBytes( from source_BA, Pos within source_BA, length of bytes required );
在执行上述行后,请注意,“源”和“目标”位置均未更改。
使用上述方法可将所需的标记字节从特定的temp_BA
放入source_BA.position = x
。
要检查任何字节(其值),请使用以下方法更新某些int
类型的变量:
阅读one-byte value:使用my_Integer = source_BA.readByte();
阅读two-byte value:使用my_Integer = source_BA.readUnsignedShort();
阅读four-byte value:使用my_Integer = source_BA.readUnsignedInt();
eight-byte value的变量Number
:使用my_Number = source_BA.readDouble();
注意:不要混淆.readByte();
,它提取(字节的)数字值与类似的.readBytes()
听起来很像,将一个字节块复制到另一个字节数组。
2)查找视频关键帧(或I帧):
[带关键帧H264 / AAC的视频标签的插图图像]
查找视频关键帧
从起始偏移量开始,使用while
循环现在[向前]遍历字节,在每个字节中搜索<9>的one-byte value(十六进制:0x09
),发现后我们再检查前面的字节以确认实际上,这是一个真实的关键帧,而不仅仅是随机出现的“ 9”。
对于H.264视频编解码器,在正确的“ 9”字节位置(xPos),我们期望前面的第11和第12个字节分别分别为“ 17”和“ 01”。If
即== true
,然后检查三个“标记大小”字节,并在此整数上加上15,以获取预期从源写入目标(temp_BA
)的字节的总长度。我们添加了15,以说明预期TAG DATA之前的11个字节和之后的4个字节。标签末尾的这4个字节是“上一个标签大小”,该数量实际上包括11个前字节,但不计算这些末尾4个字节本身。
我们告诉temp_BA
从“ 9”字节(xPos)的pos开始写入Source(您的videoByteArray
)字节,长度为“ Tag Size” +15。现在,您已经提取了一个MPEG关键帧。示例:temp_BA.writeBytes( videoByteArray, int (xPos), int (TAG_size) );
现在,可以使用以下键添加带有关键帧标记的temp_BA
:
示例:netStream.appendBytes( temp_BA ); //displays a single frame
注意:要读取3个字节的标签大小,我将显示一个自定义的转换bytes_toInt()
函数(因为处理器一次读取整数的1个,2个或4个字节,此处读取3个字节是一个笨拙的请求)。
搜索提示:标签始终在跟踪中彼此跟随。我们还可以通过检查字节是否用于非关键帧(P帧)视频标签甚至某些音频标签来更快地查找。如果是这样,那么我们检查那个特定的tag size
并现在增加我们的xPos
来跳过这个新长度。这样,我们可以跳过整个标签大小,而不仅仅是跳过单个字节。仅在具有关键帧标记时停止。
3)从视频关键帧播放:
当您考虑它时,播放就像是逐帧进行自动搜索。视频的编码帧速率定义了获取下一帧的预期速度。
因此,您的播放功能可以简单地是Timer
,它每秒获取X量的视频标签(帧)(或1000毫秒)。您以my_Timer = new Timer ( video_FPS )
为例进行操作。当计时器运行并到达每秒钟FPS片时,它将运行append_PLAY();
函数,而该函数又运行get_frame_Tag();
函数。NS.seek(0)
:将NetStream置于“搜索模式”。 (数字并不重要,但必须存在于命令中)。清除所有“提前帧”缓冲区,直到(。)帧才会更新。RESET_SEEK
:结束“搜索模式”,现在允许图像更新。使用RESET_SEEK
命令后附加的第一个标签必须是带有视频关键帧的标签。 (对于仅音频,这可以是任何标签,因为从技术上讲,所有音频标签都是音频关键帧)END_SEQUENCE
:(对于MPEG H.264)播放所有剩余的“超前帧”(填充缓冲区)。耗尽后,您现在可以附加任何类型的视频代码。请记住,H.264需要向前移动的时间戳,如果看到像素变小,则您的下一个标记时间戳是错误的(太高或太低)。如果仅添加一帧(海报图像?),则可以使用END_SEQUEMCE
清空缓冲区并显示该一帧(而无需等待缓冲区先填充x数量的帧)...
播放功能充当中间人功能来管理事物,而不会使If
语句等弄乱get frame功能。例如,管理事物意味着检查是否下载了足够的字节,甚至根据Tag Size开始获得帧。
4)一个工作示例的源代码:
代码太长。.参见下面的link:
https://gist.github.com/Valerio-Charles-VC1/657054b773dba9ba1cbc
希望能帮助到你。风投
关于actionscript-3 - AS3 NetStream AppendBytes寻求问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32182580/
我是一名优秀的程序员,十分优秀!