nonocast / me

记录和分享技术的博客
http://nonocast.cn
MIT License
20 stars 0 forks source link

学习 rtmp 开发 (Part 4: flash and ams) #273

Open nonocast opened 2 years ago

nonocast commented 2 years ago

很多同学,包括网上大量文章,在非农rtmp的时候都是直接拿起wireshark和spec一顿操作,我倒是有个建议不妨站远点去理解rtmp,会有一个非常不同的视角。

v2-1dd39f0fe20402a2307b4d7048ffde20_1440w

其中最主要的几个概念:

最早flash只是一个带交互的video clip,然后通过as扩展了交互性,也不仅局限在browser local的限制,于是有了AMF0和AMF3,其实对标的就是Web Service/SOAP以及RMI,通过这个去访问外部或者后台数据。

再然后flash就想着在浏览器里面实现视频会议的功能,所以2002年就开发了FMS(Flash Media Server),然后被Adobe收购后才改为AMS(Adobe Media Server),AMS需要被Flash所调用,所以就有了RTMP+AMF,我们看下flash是如何发布本地摄像头和声音的代码你就明白RTMP协议之根本:

nc = new NetConnection();
nc.connect("rtmp://localhost/aaaa");
nsOut = new NetStream(nc);
nsOut.attachVideo(Camera.get());
nsOut.attachAudio(Microphone.get());
nsOut.publish("1", "live");

推流的API非常直白,和RTMP的协议纹丝合缝,所以这里就有了几个概念:

最早逆向破解RTMP是为了跳开flash来实现流媒体服务,而后再是有了srs, red5, nginx-rtmp实现了rtmp server取代AMS。

我们再来看看RTMP和FLV之间密不可分的关系,

从Adobe的Fideo File Format Specification中可以看到,flv很大程度上就是前置了rtmp,

Starting with SWF files published for Flash Player 6, Flash Player can exchange audio, video, and data over RTMP connections with the Adobe Flash Media ServerTM. One way to feed data to Flash Media Server (and thus on to Flash Player clients) is from files in the FLV file format. Starting with SWF files published for Flash Player 7, Flash Player can also play FLV files directly with MIME type video/x-flv.

回顾一下FLV的结构:

我开始就好奇为什么是8,9,18,而不是1, 2, 3,其实这里就和RTMP的Message Type对上了:

所以,

最后通过rtmpdump验证如下:

rtmpdump -V -r rtmp://your-domain/app/foo -o out.flv
RTMPDump v2.4
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
DEBUG: Parsing...
DEBUG: Parsed protocol: 0
DEBUG: Parsed host    : play.nonocast.cn
DEBUG: Parsed app     : app
DEBUG: Protocol : RTMP
DEBUG: Hostname : play.nonocast.cn
DEBUG: Port     : 1935
DEBUG: Playpath : foo
DEBUG: tcUrl    : rtmp://play.nonocast.cn:1935/app
DEBUG: app      : app
DEBUG: live     : no
DEBUG: timeout  : 30 sec
DEBUG: Setting buffer time to: 36000000ms
Connecting ...
DEBUG: RTMP_Connect1, ... connected, handshaking
DEBUG: HandShake: Type Answer   : 03
DEBUG: HandShake: Server Uptime : -745572240
DEBUG: HandShake: FMS Version   : 0.0.0.0
DEBUG: RTMP_Connect1, handshaked
DEBUG: Invoking connect
INFO: Connected...
DEBUG: HandleServerBW: server BW = 5000000
DEBUG: HandleClientBW: client BW = 5000000 2
DEBUG: HandleChangeChunkSize, received: chunk size change to 8000
DEBUG: RTMP_ClientPacket, received: invoke 190 bytes
DEBUG: (object begin)
DEBUG: (object begin)
DEBUG: Property: <Name:             fmsVer, STRING: FMS/3,0,1,123>
DEBUG: Property: <Name:       capabilities, NUMBER: 31.00>
DEBUG: (object end)
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetConnection.Connect.Success>
DEBUG: Property: <Name:        description, STRING: Connection succeeded.>
DEBUG: Property: <Name:     objectEncoding, NUMBER: 0.00>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <connect>
DEBUG: sending ctrl. type: 0x0003
DEBUG: Invoking createStream
DEBUG: RTMP_ClientPacket, received: invoke 29 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <_result>
DEBUG: HandleInvoke, received result for method call <createStream>
DEBUG: SendPlay, seekTime=0, stopTime=0, sending play: foo
DEBUG: Invoking play
DEBUG: sending ctrl. type: 0x0003
DEBUG: RTMP_ClientPacket, received: invoke 96 bytes
DEBUG: (object begin)
DEBUG: Property: NULL
DEBUG: (object begin)
DEBUG: Property: <Name:              level, STRING: status>
DEBUG: Property: <Name:               code, STRING: NetStream.Play.Start>
DEBUG: Property: <Name:        description, STRING: Start live>
DEBUG: (object end)
DEBUG: (object end)
DEBUG: HandleInvoke, server invoking <onStatus>
DEBUG: HandleInvoke, onStatus: NetStream.Play.Start
Starting download at: 0.000 kB
DEBUG: RTMP_ClientPacket, received: notify 24 bytes
DEBUG: (object begin)
DEBUG: (object end)
DEBUG: HandleCtrl, received ctrl. type: 0, len: 6
DEBUG: HandleCtrl, Stream Begin 1
DEBUG: RTMP_ClientPacket, received: notify 573 bytes
DEBUG: (object begin)
DEBUG: (object begin)
DEBUG: Property: <Name:              width, NUMBER: 200.00>
DEBUG: Property: <Name:             height, NUMBER: 200.00>
DEBUG: Property: <Name:       displayWidth, NUMBER: 200.00>
DEBUG: Property: <Name:      displayHeight, NUMBER: 200.00>
DEBUG: Property: <Name:           duration, NUMBER: 0.00>
DEBUG: Property: <Name:          framerate, NUMBER: 10.00>
DEBUG: Property: <Name:                fps, NUMBER: 10.00>
DEBUG: Property: <Name:      videodatarate, NUMBER: 2500.00>
DEBUG: Property: <Name:       videocodecid, NUMBER: 7.00>
DEBUG: Property: <Name:      audiodatarate, NUMBER: 160.00>
DEBUG: Property: <Name:       audiocodecid, NUMBER: 10.00>
DEBUG: Property: <Name:            profile, STRING: >
DEBUG: Property: <Name:              level, STRING: >
DEBUG: Property: <Name:             Server, STRING: Tengine>
DEBUG: Property: <Name:     videocodecreal, NUMBER: 0.00>
DEBUG: Property: <Name:           fileSize, NUMBER: 0.00>
DEBUG: Property: <Name:    audiosamplerate, NUMBER: 48000.00>
DEBUG: Property: <Name:    audiosamplesize, NUMBER: 16.00>
DEBUG: Property: <Name:      audiochannels, NUMBER: 2.00>
DEBUG: Property: <Name:             stereo, BOOLEAN:    TRUE>
DEBUG: Property: <Name:                2.1, BOOLEAN:    FALSE>
DEBUG: Property: <Name:                3.1, BOOLEAN:    FALSE>
DEBUG: Property: <Name:                4.0, BOOLEAN:    FALSE>
DEBUG: Property: <Name:                4.1, BOOLEAN:    FALSE>
DEBUG: Property: <Name:                5.1, BOOLEAN:    FALSE>
DEBUG: Property: <Name:                7.1, BOOLEAN:    FALSE>
DEBUG: Property: <Name:            encoder, STRING: obs-output module (libobs version 27.2.4)>
DEBUG: (object end)
DEBUG: (object end)
INFO: Metadata:
INFO:   width                 200.00
INFO:   height                200.00
INFO:   displayWidth          200.00
INFO:   displayHeight         200.00
INFO:   duration              0.00
INFO:   framerate             10.00
INFO:   fps                   10.00
INFO:   videodatarate         2500.00
INFO:   videocodecid          7.00
INFO:   audiodatarate         160.00
INFO:   audiocodecid          10.00
INFO:   Server                Tengine
INFO:   videocodecreal        0.00
INFO:   fileSize              0.00
INFO:   audiosamplerate       48000.00
INFO:   audiosamplesize       16.00
INFO:   audiochannels         2.00
INFO:   stereo                TRUE
INFO:   2.1                   FALSE
INFO:   3.1                   FALSE
INFO:   4.0                   FALSE
INFO:   4.1                   FALSE
INFO:   5.1                   FALSE
INFO:   7.1                   FALSE
INFO:   encoder               obs-output module (libobs version 27.2.4)
815.438 kB / 38.55 sec^C
Caught signal: 2, cleaning up, just a second...
816.304 kB / 38.59 sec
DEBUG: RTMP_Read returned: 443
Download may be incomplete (downloaded about 0.00%), try resuming
DEBUG: Closing connection.

DEBUG: Invoking deleteStream

参考阅读