Frequently Asked Questions
How can I grab stream statistics?
QUESTION:
Can I grab the following stream statistics:
- stream start time (unix timestamp)
- stream end time (unix timestamp)
- broadcaster user agent
- video codec
- audio codec
- video size (width and height)
- FPS
- total bitrate (bits per second)
- video bitrate (bits per second)
- audio bitrate (bits per second)
- keyframe interval
ANSWER:
Many of these stats have to be calculated and many are not collected nor calculated on the server. Below I will detail how to access what is available.
To get the start time when starting publishing in the streamBroadcastStart(IBroadcastStream stream)
method
long startTime = ((ClientBroadcastStream) stream).getCreationTime();
A streams end time is not stored and I would suggest collecting that instant using the streamBroadcastClose(IBroadcastStream stream)
method in your application adapter:
long endTime = System.currentTimeMillis();
A broadcasters user-agent is available via the IConnection
which represents the current connection and may be accessed in any of the application adapter methods like so (ApplicationAdapter.connect()
shown):
@Override
public boolean connect(IConnection conn, IScope scope, Object[] params) {
Map<String, Object> connParameters = conn.getConnectParams()
String userAgent = connParameters.get("flashVer").toString();
return super.connect(conn, scope, params);
}
Connection parameters output:
{app=issues/test, tcUrl=rtmp://localhost/issues/test, audioCodecs=3575.0, path=issues/test, capabilities=239.0, swfUrl=http://localhost:5080/demos/publisher.swf, videoFunction=1.0, flashVer=LNX 22,0,0,209, videoCodecs=252.0, pageUrl=http://localhost:5080/demos/publisher.html, objectEncoding=0.0, fpad=false}
The codec ids may be accessed via these methods:
IStreamCodecInfo info = ((ClientBroadcastStream) stream).getCodecInfo()
String audioCodec = info.getAudioCodecName();
String videoCodec = info.getVideoCodecName();
Please be aware that if the video codec is not AVC/h.264 (id=7) or the audio codec is not AAC (id=10), the values may be null and to get the missing codec, you’d need to observe the AudioData
or VideoData
packets and pull the codec id’s from them and match the values: AudioCodec enumeration:
PCM((byte) 0),
ADPCM((byte) 0x01),
MP3((byte) 0x02),
PCM_LE((byte) 0x03),
NELLY_MOSER_16K((byte) 0x04),
NELLY_MOSER_8K((byte) 0x05),
NELLY_MOSER((byte) 0x06),
PCM_ALAW((byte) 0x07),
PCM_MULAW((byte) 0x08),
RESERVED((byte) 0x09),
AAC((byte) 0x0a),
SPEEX((byte) 0x0b),
MP3_8K((byte) 0x0e),
DEVICE_SPECIFIC((byte) 0x0f);
VideoCodec enumeration:
JPEG((byte) 0x01),
H263((byte) 0x02),
SCREEN_VIDEO((byte) 0x03),
VP6((byte) 0x04),
VP6a((byte) 0x05),
SCREEN_VIDEO2((byte) 0x06),
AVC((byte) 0x07);
To access metadata:
Map<Object,Object> metaData = null;
Notify notify = ((ClientBroadcastStream) stream).getMetaData();
Input reader = new Input(notify.getData());
// string datatype
reader.readDataType();
String method = reader.readString();
if (method.equals("onMetaData")) {
// object type
reader.readDataType();
metaData = (Map<Object,Object>) reader.readMap();
// now the map may be queried for key / value pairs such as width, height, fps, samplerate, audiocodecid, videocodecid etc
int width = metaData.containsKey("width") ? ((Number) metaData.get("width")).intValue();
}
Also note that if your publishing client doesn’t send metadata properties such as “fps”, they won’t be available in the map.