RecursiveAI.OneMedia.Flv: FlvDemuxer, FlvFormat (the asynchronous open runs the reader on a pool thread over a ranged source), FlvScriptTags, and the AMF
reader (Amf.cs: AMF0, and AMF3 for the AVMPLUS marker).
Structure
- Header
FLV, version, flags (audio 4, video 1), DataOffset, thenPreviousTagSize0and tags: 11-byte header (type 8 audio, 9 video, 18 script data; 24-bit size; 24+8-bit timestamp in ms; stream id) and body, each followed by a 32-bit previous-tag size. A wrong previous-tag size is an informational defect; a tag cut off by the end of the file ends reading with a defect. Tags with the filter bit (encrypted) are skipped. - Tracks come from the first tags: at most 256 tags or 8 MiB are read until every stream the header announces has its configuration. A seekable source then goes back to the first tag; a forward-only source delivers the tags already read first.
- Script data: AMF0
onMetaData(and any other leading script tag) is read losslessly as tags of systemflv. Nested objects and ECMA arrays are flattened asparent/child; arrays are listed up to 64 elements plus a container tag. Strings are text, numbers are real or integer numbers, booleans are numbers, dates are text.
Codecs and packets
- Video codec ids 2 (
flv1), 3 (flashsv), 4 (vp6f), 5 (vp6a), 6 (flashsv2), 7 (H.264,avcC), 12 (HEVC,hvcC); the Enhanced RTMP form (bit 7 of the first byte) with FourCCsavc1,hvc1,av01(av1C),vp09(vpcC),vp08,vvc1(vvcC). A sequence-start packet becomes the track's configuration and is not a packet. A changed configuration later is a defect and the track keeps the first one. - Audio: PCM (0, 3), ADPCM (1), MP3 (2, 14), Nellymoser (4, 5, 6), G.711 (7, 8), AAC (10; the AudioSpecificConfig becomes the configuration), Speex (11),
and the Enhanced FourCCs
Opus,fLaC,ac-3,ec-3,.mp3,mp4a. The sample rate and channels come from the tag flags, the AudioSpecificConfig or the first MP3 frame header. - A packet is the tag body after its own headers: for H.264/HEVC the length-prefixed NAL units as in an MP4 sample, for AAC the raw frame. The source range is that payload.
- Timestamps are milliseconds. dts = the tag timestamp; pts = dts + the composition time offset (24-bit signed) of AVC/HEVC/VVC packets. Keyframe = frame
type 1; frame type 3 (disposable) sets
Disposable; frame type 5 (command) is not a packet. A tag has no duration: durations are unknown. Duration: thedurationproperty ofonMetaDatawhen positive; otherwise, for a seekable source, the timestamp of the last tag, found from the last four bytes (the previous-tag size) with two small reads.- Seek: to the last keyframe (video) or tag (audio only) at or before the target. The table is built once by walking the tag headers of the whole file
(one 11-byte read per tag), because the
keyframesindex ofonMetaDatais optional and unreliable; this is the one scan, and only on the first seek.
Differences from ffprobe -show_packets (7.0.2)
pos: ffprobe prints the tag's offset; ours is the payload range.duration: a tag has no duration; ffprobe fills one in from the frame rate or the audio frame length, in ms; ours is unknown.
Agreement with other readers
Checked on 30 files (ffmpeg-written, with H.264/HEVC/AV1/VP9/FLV1 video and AAC/MP3/ADPCM/Nellymoser/PCM/Speex audio; one of 3.6 GB): ffprobe 7.0.2
lists 217,868 packets and so do we, with no difference after the pos and duration rules above; infocheck has no difference. ExifTool 13.60 and
MediaInfo 26.10 agree on every field except: the stereo flag of onMetaData (we list the stored value 0; ExifTool leaves a false flag out), and the
duration of a file whose onMetaData has none (3.967 s from the last tag; MediaInfo adds the last frame's length: 4.084 s).