marcandre-flvedit 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +5 -0
- data/LICENSE +24 -0
- data/README.rdoc +90 -0
- data/Rakefile +131 -0
- data/VERSION.yml +4 -0
- data/bin/flvedit +14 -0
- data/lib/flv.rb +24 -0
- data/lib/flv/audio.rb +66 -0
- data/lib/flv/base.rb +38 -0
- data/lib/flv/body.rb +57 -0
- data/lib/flv/edit.rb +20 -0
- data/lib/flv/edit/options.rb +162 -0
- data/lib/flv/edit/processor.rb +3 -0
- data/lib/flv/edit/processor/add.rb +67 -0
- data/lib/flv/edit/processor/base.rb +209 -0
- data/lib/flv/edit/processor/command_line.rb +23 -0
- data/lib/flv/edit/processor/cut.rb +27 -0
- data/lib/flv/edit/processor/debug.rb +30 -0
- data/lib/flv/edit/processor/head.rb +16 -0
- data/lib/flv/edit/processor/join.rb +52 -0
- data/lib/flv/edit/processor/meta_data_maker.rb +127 -0
- data/lib/flv/edit/processor/print.rb +13 -0
- data/lib/flv/edit/processor/printer.rb +27 -0
- data/lib/flv/edit/processor/reader.rb +30 -0
- data/lib/flv/edit/processor/save.rb +28 -0
- data/lib/flv/edit/processor/update.rb +27 -0
- data/lib/flv/edit/runner.rb +23 -0
- data/lib/flv/edit/version.rb +15 -0
- data/lib/flv/event.rb +40 -0
- data/lib/flv/file.rb +41 -0
- data/lib/flv/header.rb +37 -0
- data/lib/flv/packing.rb +140 -0
- data/lib/flv/tag.rb +62 -0
- data/lib/flv/timestamp.rb +124 -0
- data/lib/flv/util/double_check.rb +22 -0
- data/lib/flv/video.rb +73 -0
- data/test/fixtures/corrupted.flv +0 -0
- data/test/fixtures/short.flv +0 -0
- data/test/fixtures/tags.xml +39 -0
- data/test/test_flv.rb +145 -0
- data/test/test_flv_edit.rb +32 -0
- data/test/test_flv_edit_results.rb +27 -0
- data/test/test_helper.rb +9 -0
- data/test/text_flv_edit_results/add_tags.txt +132 -0
- data/test/text_flv_edit_results/cut_from.txt +114 -0
- data/test/text_flv_edit_results/cut_key.txt +20 -0
- data/test/text_flv_edit_results/debug.txt +132 -0
- data/test/text_flv_edit_results/debug_limited.txt +18 -0
- data/test/text_flv_edit_results/debug_range.txt +32 -0
- data/test/text_flv_edit_results/join.txt +237 -0
- data/test/text_flv_edit_results/print.txt +16 -0
- data/test/text_flv_edit_results/stop.txt +38 -0
- data/test/text_flv_edit_results/update.txt +33 -0
- metadata +134 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module FLV
|
2
|
+
class IOError < ::IOError # :nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
module Util # :nodoc:
|
6
|
+
def self.double_check(event, expected, actual)
|
7
|
+
Checking.fail_check(event, expected, actual) unless [*expected].include? actual
|
8
|
+
end
|
9
|
+
|
10
|
+
class Checking # :nodoc:
|
11
|
+
class << self
|
12
|
+
attr_accessor :strict
|
13
|
+
def fail_check(event, expected, actual)
|
14
|
+
err = "Mismatch on #{event}: expected #{expected} vs #{actual}"
|
15
|
+
raise IOError, err if strict
|
16
|
+
#STDERR << "Caution: "+ err
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/lib/flv/video.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module FLV
|
2
|
+
# The body of a video tag.
|
3
|
+
# The data is quite complex stuff. We make no attempt to understand it all
|
4
|
+
# or to be able to modify any of it. We simply consider it a complex string
|
5
|
+
# and read the interesting bits to give more info.
|
6
|
+
class Video < String
|
7
|
+
include Body
|
8
|
+
CODECS = Hash.new(:unknown).merge!(
|
9
|
+
1 => :JPEG,
|
10
|
+
2 => :h263,
|
11
|
+
3 => :screen,
|
12
|
+
4 => :on2_vp6,
|
13
|
+
5 => :on2_vp6_alpha,
|
14
|
+
6 => :screen_v2,
|
15
|
+
7 => :AVC
|
16
|
+
).freeze
|
17
|
+
|
18
|
+
FRAMES = Hash.new(:unknown).merge!(
|
19
|
+
1 => :keyframe ,
|
20
|
+
2 => :interframe,
|
21
|
+
3 => :disposable_interframe
|
22
|
+
).freeze
|
23
|
+
|
24
|
+
def frame_type
|
25
|
+
FRAMES[read_bits(0...4)]
|
26
|
+
end
|
27
|
+
|
28
|
+
def codec_id
|
29
|
+
read_bits(4...8)
|
30
|
+
end
|
31
|
+
|
32
|
+
def codec
|
33
|
+
CODECS[codec_id]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Dimensions for h263 encoding; either as a bit range or the final value
|
37
|
+
H263_DIMENSIONS = {
|
38
|
+
0 => [41...49, 49...57],
|
39
|
+
1 => [41...57, 57...73],
|
40
|
+
2 => [352, 288],
|
41
|
+
3 => [176, 144],
|
42
|
+
4 => [128, 96] ,
|
43
|
+
5 => [320, 240],
|
44
|
+
6 => [160, 120]
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
# Returns dimensions as {:width => w, :height => h}, for Sorensen H.263 and screen video codecs only (otherwise returns nil)
|
48
|
+
def dimensions
|
49
|
+
w, h = case codec
|
50
|
+
when :h263
|
51
|
+
H263_DIMENSIONS[read_bits(38...41)]
|
52
|
+
when :screen
|
53
|
+
[12...24, 24...32]
|
54
|
+
end
|
55
|
+
return nil unless w
|
56
|
+
w, h = [w, h].map{ |r| read_bits(r) } if w.is_a?(Range)
|
57
|
+
{:width => w, :height => h}
|
58
|
+
end
|
59
|
+
|
60
|
+
def is?(what)
|
61
|
+
frame_type.to_s.downcase == what.to_s.downcase || super
|
62
|
+
end
|
63
|
+
|
64
|
+
def getters
|
65
|
+
super - [:frame_type, :frame_type.to_s] # Let's exclude the frame_type from the normal attributes... (string vs symbol: ruby 1.8 vs 1.9)
|
66
|
+
end
|
67
|
+
|
68
|
+
def title
|
69
|
+
super + " (#{frame_type})" # ...and include it in the title instead.
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<tags>
|
3
|
+
<!-- an event cue point -->
|
4
|
+
<metatag event="onCuePoint">
|
5
|
+
<name>TestEvent1</name>
|
6
|
+
<timestamp>333</timestamp>
|
7
|
+
<parameters>
|
8
|
+
<speaker>Peter</speaker>
|
9
|
+
<says>Hello my Name is Peter.</says>
|
10
|
+
</parameters>
|
11
|
+
<type>event</type>
|
12
|
+
</metatag>
|
13
|
+
|
14
|
+
<!-- a navigation cue point -->
|
15
|
+
<metatag event="onCuePoint">
|
16
|
+
<name>TestEvent2</name>
|
17
|
+
<timestamp>1000</timestamp>
|
18
|
+
<parameters>
|
19
|
+
<index>1</index>
|
20
|
+
<title>Chapter 1</title>
|
21
|
+
</parameters>
|
22
|
+
<type>navigation</type>
|
23
|
+
</metatag>
|
24
|
+
|
25
|
+
<!-- this cuepoint overwrites the previous cue point, because of it's
|
26
|
+
identical timestamps and the overwrite parameter was set -->
|
27
|
+
|
28
|
+
<metatag event="onCuePoint" overwrite="true">
|
29
|
+
<name>TestEvent3</name>
|
30
|
+
<timestamp>1000</timestamp>
|
31
|
+
<parameters>
|
32
|
+
<index>1</index>
|
33
|
+
<title>Chapter 2</title>
|
34
|
+
</parameters>
|
35
|
+
<type>navigation</type>
|
36
|
+
</metatag>
|
37
|
+
</tags>
|
38
|
+
|
39
|
+
|
data/test/test_flv.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class TestFlv < Test::Unit::TestCase
|
4
|
+
context "Timestamp" do
|
5
|
+
context "conversion" do
|
6
|
+
{ 0 => "0.000" ,
|
7
|
+
1 => "0.001" ,
|
8
|
+
1000 => "1.000" ,
|
9
|
+
12_345 => "12.345" ,
|
10
|
+
61_000 => "1:01.000" ,
|
11
|
+
601_000 => "10:01.000" ,
|
12
|
+
3600_000 => "1:00:00.000"
|
13
|
+
}.each do |n, s|
|
14
|
+
should "convert between #{s} and #{n} ms" do
|
15
|
+
assert_equal s, FLV::Timestamp.in_milliseconds(n).to_s
|
16
|
+
assert_equal n, FLV::Timestamp.try_convert(s).in_milliseconds
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
{ "0" => 0 ,
|
21
|
+
"1" => 1000,
|
22
|
+
"1.0" => 1000,
|
23
|
+
"1m" => 60_000,
|
24
|
+
"1h" => 60 * 60_000,
|
25
|
+
"1::" => 60 * 60_000,
|
26
|
+
"1h23m45.6789" => 60 * 60_000 + 23*60_000 + 45678
|
27
|
+
}.each do |s, n|
|
28
|
+
should "convert #{s} to #{n} ms" do
|
29
|
+
assert_equal n, FLV::Timestamp.try_convert(s).in_milliseconds
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "TimestampRange" do
|
36
|
+
context "conversion" do
|
37
|
+
{ "1:02-" => 62..(1/0.0),
|
38
|
+
"-1.23" => 0..1.23,
|
39
|
+
"12345-1:02:03.456" => 12345..3723.456,
|
40
|
+
"2m.345-1h" => 120.345..3600
|
41
|
+
}.each do |s, r|
|
42
|
+
should "convert #{s} to #{r} ms" do
|
43
|
+
assert_equal r, FLV::TimestampRange.try_convert(s).in_seconds
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
BIT_TEST = "\x01\x02\xff"
|
51
|
+
context "Bit reading from #{BIT_TEST.inspect}" do
|
52
|
+
setup do
|
53
|
+
@body = BIT_TEST.clone
|
54
|
+
class <<@body
|
55
|
+
include FLV::Body
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
[ [0..0, 0],
|
60
|
+
[0...7, 0],
|
61
|
+
[0..7, 1],
|
62
|
+
[6..7, 1],
|
63
|
+
[7..7, 1],
|
64
|
+
[14, 1],
|
65
|
+
[3..9, 0b100],
|
66
|
+
[3...15,0b1_0000_001],
|
67
|
+
[3..15, 0b1_0000_0010],
|
68
|
+
[3..16, 0b1_0000_0010_1]
|
69
|
+
].each do |bits, val|
|
70
|
+
should "return #{val} for bits #{bits}" do
|
71
|
+
assert_equal val, @body.read_bits(bits)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "Packing" do
|
77
|
+
context "a header" do
|
78
|
+
setup do
|
79
|
+
@header = FLV::Header.new
|
80
|
+
@header.extra = "hello"
|
81
|
+
@header.has_audio = true
|
82
|
+
end
|
83
|
+
|
84
|
+
should "work" do
|
85
|
+
assert_equal "FLV\001\004\000\000\000\016hello\000\000\000\000",
|
86
|
+
@header.pack
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "an audio tag" do
|
91
|
+
setup do
|
92
|
+
@tag = FLV::Tag.new(FLV::Timestamp.in_milliseconds(0x1234), FLV::Audio.new("bogus audio data!"))
|
93
|
+
end
|
94
|
+
|
95
|
+
should "work" do
|
96
|
+
assert_equal "\b\000\000\021\000\x12\x34\000\000\000\000bogus audio data!\000\000\000\034",
|
97
|
+
@tag.pack
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "Unpacking" do
|
103
|
+
setup do
|
104
|
+
@io = StringIO.new("FLV\001\004\000\000\000\016hello\000\000\000\000!!")
|
105
|
+
@header = @io.packed.read(FLV::Header)
|
106
|
+
end
|
107
|
+
|
108
|
+
should "read the header correctly" do
|
109
|
+
assert_equal "hello", @header.extra
|
110
|
+
assert_equal true, @header.has_audio
|
111
|
+
assert_equal false, @header.has_video
|
112
|
+
end
|
113
|
+
|
114
|
+
should "read just what's required" do
|
115
|
+
assert_equal "!!", @io.read
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "Typematch" do
|
120
|
+
setup do
|
121
|
+
@chunks = FLV::File.open(SHORT_FLV).each.first(4)
|
122
|
+
end
|
123
|
+
|
124
|
+
should "work" do
|
125
|
+
assert_equal false, @chunks[2].is?(:audio)
|
126
|
+
end
|
127
|
+
|
128
|
+
{
|
129
|
+
:header => [true , false, false, false],
|
130
|
+
:tag => [false, true , true , true ],
|
131
|
+
:audio => [false, false, false, false],
|
132
|
+
:audio_tag => [false, false, true , false],
|
133
|
+
:nellymoser => [false, false, false, false],
|
134
|
+
:mP3 => [false, false, true , false],
|
135
|
+
:event_tag => [false, true , false, false],
|
136
|
+
:onMetaData => [false, true , false, false],
|
137
|
+
:onCuePoint => [false, false, false, false],
|
138
|
+
}.each do |check, answers|
|
139
|
+
should "work for #{check}" do
|
140
|
+
assert_equal answers, @chunks.map{|t| t.is?(check) }, check
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class TestFlvEdit < Test::Unit::TestCase
|
4
|
+
context "Options parsing" do
|
5
|
+
setup do
|
6
|
+
@options = FLV::Edit::Options.new([SHORT_FLV, "--Debug"])
|
7
|
+
end
|
8
|
+
|
9
|
+
should "detect files" do
|
10
|
+
assert_equal [SHORT_FLV], @options.options[:files]
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
context "Command line tool" do
|
16
|
+
setup do
|
17
|
+
File.delete(TEMP_FLV) if File.exist?(TEMP_FLV)
|
18
|
+
end
|
19
|
+
|
20
|
+
should "save" do
|
21
|
+
assert !File.exist?(TEMP_FLV)
|
22
|
+
runner = FLV::Edit::Runner.new([SHORT_FLV, "--Update", "--Save", TEMP_FLV])
|
23
|
+
runner.options[:dont_catch_errors] = true
|
24
|
+
runner.run
|
25
|
+
assert File.exist?(TEMP_FLV)
|
26
|
+
end
|
27
|
+
|
28
|
+
teardown do
|
29
|
+
File.delete(TEMP_FLV) if File.exist?(TEMP_FLV)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class TestFlvEdit < Test::Unit::TestCase
|
4
|
+
context "Command line results" do
|
5
|
+
Dir.glob(File.dirname(__FILE__)+"/text_flv_edit_results/*.txt").each do |fn|
|
6
|
+
sep, args, sep, *expect = File.readlines(fn).map!(&:chomp)
|
7
|
+
args = args.split(' ')
|
8
|
+
args.unshift SHORT_FLV unless args.first.start_with?(".")
|
9
|
+
|
10
|
+
context "for 'flvedit #{args.join(' ')}'" do
|
11
|
+
setup do
|
12
|
+
Time.stubs(:now).returns(Time.utc(2008,"dec",20))
|
13
|
+
@result = ""
|
14
|
+
runner = FLV::Edit::Runner.new(args)
|
15
|
+
runner.options[:dont_catch_errors] = true
|
16
|
+
runner.options[:out] = StringIO.new(@result)
|
17
|
+
runner.run
|
18
|
+
end
|
19
|
+
should "match #{fn}" do
|
20
|
+
@result = @result.split("\n")
|
21
|
+
same = @result & expect
|
22
|
+
assert_equal expect-same, @result-same
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'backports'
|
4
|
+
require_relative '../lib/flv/edit'
|
5
|
+
require 'shoulda'
|
6
|
+
require 'mocha'
|
7
|
+
|
8
|
+
SHORT_FLV = File.dirname(__FILE__) + "/fixtures/short.flv"
|
9
|
+
TEMP_FLV = File.dirname(__FILE__) + "/fixtures/short_temp.flv"
|
@@ -0,0 +1,132 @@
|
|
1
|
+
*** command:
|
2
|
+
--Add ./test/fixtures/tags.xml --Debug
|
3
|
+
*** result:
|
4
|
+
Header| ./test/fixtures/short.flv
|
5
|
+
| extra :
|
6
|
+
| has_audio : true
|
7
|
+
| has_video : true
|
8
|
+
| version : 1
|
9
|
+
0.000 | FLV::Event tag
|
10
|
+
| event : onMetaData
|
11
|
+
| audiocodecid : 2
|
12
|
+
| audiodatarate : 16
|
13
|
+
| audiodelay : 0
|
14
|
+
| canSeekToEnd : 1
|
15
|
+
| creationdate : Fri Feb 03 122553 2006\n
|
16
|
+
| duration : 16.9
|
17
|
+
| framerate : 10
|
18
|
+
| height : 154
|
19
|
+
| videocodecid : 4
|
20
|
+
| videodatarate : 40
|
21
|
+
| width : 192
|
22
|
+
0.000 | FLV::Audio tag
|
23
|
+
| channel : mono
|
24
|
+
| codec_id : 2
|
25
|
+
| format : MP3
|
26
|
+
| rate : 11000
|
27
|
+
| sample_size : 16
|
28
|
+
0.000 | FLV::Video tag (keyframe)
|
29
|
+
| codec : on2_vp6
|
30
|
+
| codec_id : 4
|
31
|
+
| dimensions : nil
|
32
|
+
0.052 | FLV::Audio tag
|
33
|
+
0.100 | FLV::Video tag (interframe)
|
34
|
+
0.104 | FLV::Audio tag
|
35
|
+
0.156 | FLV::Audio tag
|
36
|
+
0.200 | FLV::Video tag (keyframe)
|
37
|
+
0.208 | FLV::Audio tag
|
38
|
+
0.261 | FLV::Audio tag
|
39
|
+
0.300 | FLV::Video tag (interframe)
|
40
|
+
0.313 | FLV::Audio tag
|
41
|
+
0.365 | FLV::Audio tag
|
42
|
+
0.400 | FLV::Video tag (interframe)
|
43
|
+
0.417 | FLV::Audio tag
|
44
|
+
0.470 | FLV::Audio tag
|
45
|
+
0.500 | FLV::Video tag (interframe)
|
46
|
+
0.522 | FLV::Audio tag
|
47
|
+
0.574 | FLV::Audio tag
|
48
|
+
0.600 | FLV::Video tag (interframe)
|
49
|
+
0.626 | FLV::Audio tag
|
50
|
+
0.679 | FLV::Audio tag
|
51
|
+
0.700 | FLV::Video tag (interframe)
|
52
|
+
0.731 | FLV::Audio tag
|
53
|
+
0.783 | FLV::Audio tag
|
54
|
+
0.800 | FLV::Video tag (interframe)
|
55
|
+
0.835 | FLV::Audio tag
|
56
|
+
0.888 | FLV::Audio tag
|
57
|
+
0.900 | FLV::Video tag (interframe)
|
58
|
+
0.940 | FLV::Audio tag
|
59
|
+
0.992 | FLV::Audio tag
|
60
|
+
1.000 | FLV::Video tag (interframe)
|
61
|
+
1.044 | FLV::Audio tag
|
62
|
+
1.097 | FLV::Audio tag
|
63
|
+
1.100 | FLV::Video tag (interframe)
|
64
|
+
1.149 | FLV::Audio tag
|
65
|
+
1.200 | FLV::Video tag (interframe)
|
66
|
+
1.201 | FLV::Audio tag
|
67
|
+
1.253 | FLV::Audio tag
|
68
|
+
1.300 | FLV::Video tag (interframe)
|
69
|
+
1.306 | FLV::Audio tag
|
70
|
+
1.358 | FLV::Audio tag
|
71
|
+
1.400 | FLV::Video tag (interframe)
|
72
|
+
1.410 | FLV::Audio tag
|
73
|
+
1.462 | FLV::Audio tag
|
74
|
+
1.500 | FLV::Video tag (interframe)
|
75
|
+
1.515 | FLV::Audio tag
|
76
|
+
1.567 | FLV::Audio tag
|
77
|
+
1.600 | FLV::Video tag (interframe)
|
78
|
+
1.619 | FLV::Audio tag
|
79
|
+
1.671 | FLV::Audio tag
|
80
|
+
1.700 | FLV::Video tag (interframe)
|
81
|
+
1.724 | FLV::Audio tag
|
82
|
+
1.776 | FLV::Audio tag
|
83
|
+
1.800 | FLV::Video tag (interframe)
|
84
|
+
1.828 | FLV::Audio tag
|
85
|
+
1.880 | FLV::Audio tag
|
86
|
+
1.900 | FLV::Video tag (interframe)
|
87
|
+
1.933 | FLV::Audio tag
|
88
|
+
1.985 | FLV::Audio tag
|
89
|
+
2.000 | FLV::Video tag (interframe)
|
90
|
+
2.037 | FLV::Audio tag
|
91
|
+
2.089 | FLV::Audio tag
|
92
|
+
2.100 | FLV::Video tag (interframe)
|
93
|
+
2.142 | FLV::Audio tag
|
94
|
+
2.194 | FLV::Audio tag
|
95
|
+
2.200 | FLV::Video tag (interframe)
|
96
|
+
2.246 | FLV::Audio tag
|
97
|
+
2.298 | FLV::Audio tag
|
98
|
+
2.300 | FLV::Video tag (interframe)
|
99
|
+
2.351 | FLV::Audio tag
|
100
|
+
2.400 | FLV::Video tag (interframe)
|
101
|
+
2.403 | FLV::Audio tag
|
102
|
+
2.455 | FLV::Audio tag
|
103
|
+
2.500 | FLV::Video tag (interframe)
|
104
|
+
2.507 | FLV::Audio tag
|
105
|
+
2.559 | FLV::Audio tag
|
106
|
+
2.600 | FLV::Video tag (interframe)
|
107
|
+
2.612 | FLV::Audio tag
|
108
|
+
2.664 | FLV::Audio tag
|
109
|
+
2.700 | FLV::Video tag (interframe)
|
110
|
+
2.716 | FLV::Audio tag
|
111
|
+
2.768 | FLV::Audio tag
|
112
|
+
2.800 | FLV::Video tag (interframe)
|
113
|
+
2.821 | FLV::Audio tag
|
114
|
+
2.873 | FLV::Audio tag
|
115
|
+
2.900 | FLV::Video tag (interframe)
|
116
|
+
2.925 | FLV::Audio tag
|
117
|
+
2.977 | FLV::Audio tag
|
118
|
+
3.000 | FLV::Video tag (interframe)
|
119
|
+
3.030 | FLV::Audio tag
|
120
|
+
3.082 | FLV::Audio tag
|
121
|
+
3.100 | FLV::Video tag (interframe)
|
122
|
+
3.134 | FLV::Audio tag
|
123
|
+
3.186 | FLV::Audio tag
|
124
|
+
3.200 | FLV::Video tag (interframe)
|
125
|
+
3.239 | FLV::Audio tag
|
126
|
+
3.291 | FLV::Audio tag
|
127
|
+
3.300 | FLV::Video tag (interframe)
|
128
|
+
3.343 | FLV::Audio tag
|
129
|
+
3.395 | FLV::Audio tag
|
130
|
+
3.400 | FLV::Video tag (interframe)
|
131
|
+
3.448 | FLV::Audio tag
|
132
|
+
3.500 | FLV::Video tag (interframe)
|