Incremental Operations

April 5, 2009

Announcing Flazr – download RTMP (Flash video) streams

Filed under: java, open source — Tags: , , , , , , — Peter Thomas @ 6:17 am

A quick post to announce my new open-source project: http://flazr.com

I had done most of the coding early this year and was really feeling bad about sitting on the code and not having time to package and release as open source. Judging by the number of hits I keep getting on this blog entry I made previously on “how to download RTMP streams with Red5” – there appears to be a lot of demand for this.

Flazr is a Java implementation of the RTMP protocol using the excellent Apache Mina project. I think I was able to come up with a far more concise and readable implementation than what the Red5 project uses – which is not that surprising – because the scope of Red5 is much bigger and Flazr focuses only on the client side. I do feel that Flazr will be useful as an additional reference for those interested in understanding the details of the RTMP protocol.

One of the highlights of Flazr (especially from a Java perspective) is the usage of Groovy for scripting. Groovy allows the end-user to script things such as scraping the HTML from a given URL, parsing it and then invoking the RTMP client routine with the right parameters. All this in a platform-independent manner, without the need to compile anything and using a normal text-editor. I expect Flazr’s Groovy approach to be much easier to use (and arguably more powerful) than the PERL-driven approach that projects like “get_iplayer” and “rtmpdump” use.

Flazr has been designed so that end-users can extend the capabilities far beyond what the core supports – using just some plain-text Groovy scripts. This means that end-users won’t need to depend on the project team (*ahem* just me for now :) to pitch in and make changes. I’m quite interested to see how this turns out in practice.

All in all I’m quite positive about Groovy’s useful-ness, the example scripts that come with the Flazr distribution demonstrate usage of the nifty XmlSlurper and implementing a Java interface on-the-fly. End users should be able to even plug in third-party libraries if they so desire and make use of all that the JVM offers.

16 Comments »

  1. Hi Peter,

    I used the very cool groovy scripting capability of Flazr to write a small script for downloading (free) videos from RTLNow. Unfortunately every download stops after about 30 seconds of downloaded video. Do you have any idea why this might happen? Do you plan to include a resume option to Flazr to enable continuing aborted downloads (like RTMPDump has)?

    Here’s the script I used for my tests:

    import com.flazr.*

    // RTLNow video downloading
    def videoId = “11811″
    println “videoId: ‘” + videoId + “‘”

    // Get XML containing information about video with given ID
    def url = “http://rtl-now.rtl.de/logic/generate_film_xml08.php?para1=” + videoId
    def xml = Utils.getOverHttp(url)

    // Extract infos for downloading video
    def data = new XmlSlurper().parseText(xml)
    def videoinfo = data.playlist.videoinfo[0]
    def filename = videoinfo.filename.text()
    println “filename: ‘” + filename + “‘”
    def title = videoinfo.title.text()
    println “title: ‘” + title + “‘”
    def dbApiURL = data.dbApiURL.text()

    // Only proceed if protocol is RTMP
    if (filename.startsWith(‘rtmp://’)) {
    // Extract parameters
    def posFirstSlash = filename.indexOf(‘/’, new String(“rtmp://”).length()+1)
    def posSecondSlash = filename.indexOf(‘/’, posFirstSlash+1)
    def tcUrl = filename.substring(0, posSecondSlash + 1)
    println “tcUrl: ‘” + tcUrl + “‘”
    def playParam = filename.substring(tcUrl.length(),filename.lastIndexOf(‘.flv’))
    println “playParam: ‘”+playParam+”‘”
    def host = tcUrl.substring(new String(“rtmp://”).length())
    def app = host.substring(host.indexOf(‘/’, 0)+1, host.indexOf(‘/’, host.indexOf(‘/’, 0)+1))
    host = host.substring(0, host.indexOf(‘/’, 0))
    println “host: ‘”+host+”‘”
    println “app: ‘”+app+”‘”

    def session = new RtmpSession(host, 1935, app, playParam, title+”.flv”)
    params = session.connectParams

    def pageUrl = dbApiURL.substring(0, dbApiURL.indexOf(‘/’, new String(“http://”).length()+1)+1)

    params.flashVer = “WIN 10,0,22,87″
    params.tcUrl = tcUrl
    params.pageUrl = pageUrl
    params.swfUrl = pageUrl

    println “params.flashVer: ‘”+params.flashVer+”‘”
    println “params.tcUrl: ‘”+params.tcUrl+”‘”
    println “params.pageUrl: ‘”+params.pageUrl+”‘”
    println “params.swfUrl: ‘”+params.swfUrl+”‘”
    println params

    // Start downloading
    RtmpClient.connect session

    } else {

    // No RTMP protocol
    println (“No RTMP protocol in: ‘”+filename+”‘”)
    println (“Aborting.”)

    }

    Comment by Max Mustermann — April 30, 2009 @ 2:48 am

  2. @max – I’ll have to try this when I get time. Yes, resume should be something on the roadmap.

    P.S. you can also use the Flazr project forums / tracker at SourceForge.

    Comment by Peter Thomas — April 30, 2009 @ 4:41 am

  3. Hey,

    i’m trying to get it working with this stream :

    http://www.oc-tv.net/sonic-youth,concert-live.htm

    but when i try to see the informations about the handshake, wireshark does not show rtmp layer (it seems encrypted). What do you think?

    Comment by Tom — May 8, 2009 @ 8:53 pm

  4. Hi Peter,

    since I don’t want you to give me full commitement rights to your source base, I would suggest the following changes using this wonderful blog:

    The affected source file is “AmfProperty.java”.
    In order to download a special rtmp stream, I had to add the following AMF data type to the enum “Type”:
    BYTE_ARRAY(0×0C)

    Additionally, the following lines have to be added into the switch-block within the method decode:

    case BYTE_ARRAY:
    int baSize = in.getInt();
    in.position(in.position() + baSize);
    break;

    Cheers,
    Patrick

    Comment by Patrick — May 10, 2009 @ 1:41 am

  5. @Patrick

    Thanks! I just checked in some changes including what you pointed out. It is actually “long string” as per AMF0 – in AMF3 0×0C is “byte array” as you said. You can refer this for more details:

    http://opensource.adobe.com/wiki/download/attachments/1114283/amf0_spec_121207.pdf

    Comment by Peter Thomas — June 4, 2009 @ 7:40 pm

  6. Hi Peter,

    Congratulations on a great piece of work! Do you have any groovy scripts or related illustrating use of your new RTMPE support?

    Brian

    Comment by Brian McGann — June 8, 2009 @ 6:39 pm

  7. @Brian

    There are a couple of examples bundled with the Flazr distribution. You can find more information at the wiki off the home page here:

    http://apps.sourceforge.net/mediawiki/flazr

    Comment by Peter Thomas — June 8, 2009 @ 7:42 pm

  8. @Brian oops I read your comment in a hurry :P

    The ‘E’ support is checked into SVN trunk but not released as a distribution yet. Look at the main method in this file, that should be all you need to get started.

    Comment by Peter Thomas — June 8, 2009 @ 7:48 pm

  9. Have looked at implementing rtmpt?

    Comment by Glyn — June 22, 2009 @ 3:38 pm

  10. Hi Peter,

    Thanks for the reply on June 8: things are working well! Very, very cool. By any chance do you have any relevant groovy script example for this new stuff?

    Comment by Brian McGann — June 23, 2009 @ 6:33 am

  11. Hi,
    I have red5 server installed and working fine with flash client. I have to write a java client which can show live video stream in Java frame.
    Please tell me how to do that.
    If I use JMF then is any way to render streams in java?

    Regards
    Santosh

    Comment by CentOS — July 23, 2009 @ 6:29 pm

  12. @Santosh

    This is an interesting requirement, because it sounds like you will end up creating a replacement for the Adobe Flash Player. Adobe won’t be happy :)

    I don’t think this will be easy, if you look at this JMF sample, you may get some idea on how to get some arbitrary stream into JMF:

    http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/solutions/ScreenGrabber.html

    Using the Flazr project, you will be able to get the raw bytes of each incoming frame. Video could be in H.263 or H.264 format. The tough part will be converting this into a format supported by JMF. Maybe JMF already supports H.263 / H.264 – but I don’t know.

    You can also look at the code of this JMF wrapper for ffmpeg, that may give you some ideas:

    http://sourceforge.net/projects/jffmpeg

    Comment by Peter Thomas — July 23, 2009 @ 6:40 pm

  13. Hi,Sir
    I need some help on Flazr.
    When I am watching the videos on NBC.com,(http://www.nbc.com/saturday-night-live/video/episodes/?vid=1163334#vid=1163334).I use Replay Media Catcher and Wireshark to catch these packets:

    [edit moved large content to here]

    Comment by Kankaqi — October 23, 2009 @ 8:38 pm

  14. I hope that one of the fixes took care of this, not sure. Can you download the file from here:

    http://flazr.com/files/

    And replace the existing JAR file you use, (either rename this file or edit the flazr.bat), let me know how it goes. If this doesn’t fix it, you may have to wait a while, really busy, you could try hack the source of course…

    Comment by Peter Thomas — October 23, 2009 @ 8:46 pm

  15. Thanks for your reply, sir.
    I tried flazr-0.6.jar, it doesnt work either.
    I have used Wireshark to catch every packet (you can see that in my previous post)and analyze it.I think i am almost there, but some parameters are wrong. I will pay you 10 dollars(via paypal) if you can help me solve this problem.
    I have also used RTMPDUMP, it wont work either.
    Here is the log produced by RTMPDUMP.1.6:

    [edit moved large content to here]

    I can connect successfully by using both Flazr and RTMPDUMP, but neither will download successfully.No idea why this happened.

    And, this video uses SWF verification, which means the swfurl parameter must be “http://www.nbc.com/assets/video/3-0/swf/videoplayer_extension.swf”.

    You can see my Email address.If you can help me or have any suggestions, Please contact me or just reply here.I will pay you 10 dollars for your help.Thanks a lot.

    Best Regards, Kankaqi

    Comment by Kankaqi — October 24, 2009 @ 11:16 pm

  16. Hello,

    I’m using a modified version of the “videolectures.groovy” script to download a file from a rtmp streaming server. Unfortunately, I hit the following exception:

    22:45:47,338 [AnonymousIoService-12] INFO [RtmpDecoder] – onStatus code: NetStream.Play.Start
    22:45:47,393 [AnonymousIoService-13] INFO [RtmpDecoder] – server notify: [[STRING(0x02) |RtmpSampleAccess], [BOOLEAN(0x01) false]]
    22:45:47,393 [AnonymousIoService-13] INFO [RtmpDecoder] – server notify: [[STRING(0x02) onStatus], [OBJECT(0x03) [[STRING(0x02) code: NetStream.Data.Start]]]]
    22:45:47,404 [AnonymousIoService-13] ERROR [RtmpClient] – exceptionCaught:
    org.apache.mina.filter.codec.ProtocolDecoderException: java.nio.BufferUnderflowException

    with a big hexdump following the exception.

    flazr is able to connect to the server and seems to start downloading the file. The audio (I’m trying to download an audio-only file) format seems not to be recognized by the RTMP decoder.

    Thanks for your help and the great software!

    Comment by Greg — October 30, 2009 @ 3:49 am


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.