Play stream with ffmpeg (ffplay)

In our project we have to feed a VOD stream from Wowza to FFmpeg. The stream plays fine over RTMP, but I was wondering how that worked - what kind of request FFmpeg sends to Wowza etc. Essentially I want to be able to parse that request and return a file stream depending on the request string.

I know that with a Flash client I could use method play() on a server module. Is there any such option for when the client is FFmpeg?

Also, an interesting moment: when I have some directory structure under my ‘content’ folder, I can navigate it with FFmpeg just fine by submitting a request like the following:

ffplay “rtmp://wowza:1935/vod/definst/some_dir_under_content/vod_file.flv”

However, that doesn’t work with a Flash client - says “Stream not found”. Although the latter is not a problem at all (I can - and prefer to - use play() to juggle streams and files), I was just wondering what the difference was between how those clients communicate with Wowza.

Any clarification would be much appreciated.

Not sure what you’re going for (and I’m reasonably certain I’m not going to be the person to help you with it!), but can you clarify a bit more? Are you looking to pull a series of files with FFMPEG? Or part of a file?

Hi,

If ffplay is making a normal rtmp request and you can play the full url back then you should be able to do the following.

Your module will need to implement the IStreamNameAliasProvider interface. This will provide 2 methods, resolvePlayAlias & resolveStreamAlias. resolvePlayAlias is the one you will be using to re-map the stream name. resolveStreamAlias will not be called for vod but you should return the input name for completeness.

Override ModuleCore.play. This is where the play command from the player will be received. Here you will convert your start & duration url variables into parameters to pass to the ModuleCore.play method.

Your queryString parameters should be available in client.getQueryStr().

The params field contains the initial settings.

PARAM1 is the stream name. You could re-map it here but it is better to do that using the resolvePlayAlias method.

PARAM2 is the start time in milliseconds.

PARAM3 is the duration in milliseconds.

PARAM4 is reset. With a custom flash client, it is possible to call play multiple times to create a playlist which will switch seamlessly. reset is used to reset the playlist. It most likely will not work with ffplay as it probably cannot handle the multiple play requests.

You should also create a custom MediaReader to override MediaReaderFLV or MediaReaderH264 to set the metadata duration to the modified duration.

Call invokePrevious passing your modified params AMFDataList to invoke the ModuleCore.play method. If play is being overridden in any other modules between yours and ModuleCore then these will be invoked first. None of the std modules invoke this method. You can see what methods each module invokes when you have debug logging enabled.

If you implement IStreamNameAliasProvider then in resolvePlayAlias, return the full path to the vod file. This will be called from ModuleCore.play for every stream.

https://www.wowza.com/docs/how-to-insert-a-pre-roll-or-mid-roll-for-video-on-demand-playback-in-flash-rtmp-client shows how to invoke play to modify params and also create a custom Mediareader to handle the modified duration.

You may also need to have a custom getStreamLength method for the player to call. Some players call this before play to get the duration (JW Player).

	public void getStreamLength(IClient client, RequestFunction function, AMFDataList params) {
		double duration = calculate duration from QueryString;
		sendResult(client, params, duration);
	}

Hope this helps.

Roger.

I’m sure that’s possible with a custom server-side module, if nothing else. Just something to parse the URL variables and call the appropriate internal Wowza commands.

I assume FFMPEG’s RTMP request must call some kind of play method, right? I mean, it plays, doesn’t it? :slight_smile:

Check your Wowza logs. Maybe turn on debug logging if necessary, to see what an FFMPEG request actually does.

I am curious what FFMPEG might do with a server-side Wowza playlist. But otherwise, if you create a custom Wowza server-side module, you should be able to intercept the stream name and URL parameters, then use those to control your start and duration times for that stream, right? Then you’d just have to use a series of FFMPEG calls to simulate a playlist client-side. See the note here about query parameters for single URL RTMP clients (which should include FFMPEG):

https://www.wowza.com/docs/how-to-format-adobe-flash-rtmp-urls

Hello, susta004, thank you for your comment. I’ll try to clarify more what I intend to do.

Our Wowza server processes live streams and records them in segments to also stream later as vods. Another server has to connect to Wowza and analyze video data in both live and vod streams using FFmpeg. When analyzing vods, it may be either pulling a series of files or a part of a file, depending on which part of the archive has to be analyzed.

I wish to make a request from the FFmpeg application to Wowza to play a specific part of the recorded vod archive, but I don’t want to request full path to the file under ‘contents’, instead I wish to add more abstract parameters to the request.

Like this:

ffplay “rtmp://wowza:1935/vod/play_recording?starttime=134567654&duration=36200”

instead of this:

ffplay “rtmp://wowza:1935/vod/definst/some_dir_under_content/vod_file.flv”

Well, it’s definitely possible when the client is a Flash application that calls NetStream.play(streamName, startTime, duration).

But from what I read on the forum, it looks like Flash client is the only option to make a playlist of several vods on the server side.

Also that’s the only way, that I know of, to intercept the ‘play’ request from a client - because all the parameters are supplied to ModuleCore.play() method.

It’s okay if I can’t play the streams in a server-side playlist with FFmpeg, I could do with separate vod requests. But I’d love to know how to abstract from full file paths of those vods.

susta004, thank you for suggestions and the note about query parameters. However, FFmpeg doesn’t call ModuleCore.play() so I don’t think I can use that approach.

Roger, thank you for such detailed reply. Although I have already studied the tutorial to which you have added the link, I didn’t know about getStreamLength. And IStreamNameAliasProvider looks very promising, I’ll see if it works for me.

I stand corrected: FFmpeg does call ModuleCore.play()

I’m not sure why it didn’t call it for me in earlier tests, I probably messed up the query string.

This means that Wowza does not make any distinction between Flash and FFmpeg clients, at least as far as my application is concerned, which answers my initial question in the simplest way possible.