ID3 text tags for IOS

Hi,

I’m developing an iOS app to stream live in-car video from a racing car with synchronized data. In order to provide a reference for the data, I’ve been trying to insert a Unix timestamp as a text ID3 tag. I’ve adapted the code from here https://www.wowza.com/docs/how-to-add-poster-frames-to-apple-http-streams-id3-metadata-for-app-store-audio-renditions to do so.

At the moment my code just inserts the Unix time that the packetizer started in every frame.

Unfortunately the iOS metadata API functions aren’t detecting the tags. This is strange, because I’ve tested the same code with a different HLS source also containing ID3s- a VOD m3u8 playlist containing chunks with ID3s created using Apple’s own tools. The iOS code works fine with this video- all tags are detected. I’ve verified that the chunks from Wowza do contain ID3s- although seemingly only one at the beginning of each chunk.

I’ve examined the resulting chunks in a hex editor, and I’ve noticed that the Wowza-inserted chunk appends its ID3 to a TS PMT packet - hex dump below. This packet is over the standard 188 bytes- the ID3 is just stuck on the end.

The highlighted numbers are the PMT table ID and the ID3 tag

47 4F FF 10 00 02 B0 3C 00 01 C1 00 00 E1 00 F0 11 25 0F FF FF 49 44 33 20 FF 49 44 33 20 00 1F 00 01 15 E1 02 F0 0F 26 0D FF FF 49 44 33 20 FF 49 44 33 20 00 0F 1B E1 00 F0 00 04 E1 01 F0 00 48 81 B9 18 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 44 33 04 00 10 00 00 00 13 54 58 58 58 00 00 00 09 00 00 03 54 65 73 74 54 65 78 74 33 44 49 04 00 10 00 00 00 13

In contrast the Apple produced tag is in a PES packet which is 188 bytes long (Apple’s docs state that HLS metadata should be carried in a PES):

47 41 03 10 00 00 01 0D 00 B2 84 80 90 21 00 37 77 41 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 44 33 04 00 00 00 00 00 15 54 58 58 58 00 00 00 0B 00 00 03 00 54 65 73 74 54 65 78 74 00

I’m wondering if I’m doing something wrong at the Wowza end, causing the tag to be inserted in the wrong place, and thus not correctly read - I suspect I’m misunderstanding some part of the API

I should also mention, that for testing purposes I’m using VLC to create a fake live stream from a file, and that previously, while trying to use Apple’s live stream segmenter together with their ID3 inserter, I’ve run into trouble- and discovered on a post on an Apple developer forum that there is a known issue with trying to insert ID3s into MPEG2TS feeds from VLC, due to the fact that VLC apparently pads the MPEG2TS PMT with the adaptation field.

My code is

package com.cosworth.wms.module;

import com.wowza.wms.application.*;

import com.wowza.wms.module.*;

import com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.*;

import com.wowza.wms.media.mp3.model.idtags.*;

import com.wowza.wms.stream.livepacketizer.*;

public class Id3TagInserter2 extends ModuleBase {

class LiveActionNotify implements ILiveStreamPacketizerActionNotify

{

private IApplicationInstance appInstance = null;

public LiveActionNotify(IApplicationInstance appInstance)

{

this.appInstance = appInstance;

}

public void onLiveStreamPacketizerCreate(ILiveStreamPacketizer liveStreamPacketizer, String streamName)

{

}

public void onLiveStreamPacketizerDestroy(ILiveStreamPacketizer liveStreamPacketizer)

{

}

public void onLiveStreamPacketizerInit(ILiveStreamPacketizer liveStreamPacketizer, String streamName)

{ getLogger().info(“LIVE STREAM PACKETIZER INIT”);

while(true)

{

if (!(liveStreamPacketizer instanceof LiveStreamPacketizerCupertino))

break;

LiveStreamPacketizerCupertino cupertinoPacketizer = (LiveStreamPacketizerCupertino)liveStreamPacketizer;

ID3Frames id3Header = cupertinoPacketizer.getID3FramesHeader();

if (id3Header == null)

break;

Long unixTime = System.currentTimeMillis();

String time = unixTime.toString();

getLogger().info(“ABOUT TO ADD TEXT FRAME START TIMESTAMP”+time+"");

ID3V2FrameTextInformation frame = new ID3V2FrameTextInformation(ID3V2FrameBase.TAG_TXXX);

frame.setValue(time);

id3Header.putFrame(frame);

break;

}

}

}

public void onAppStart(IApplicationInstance appInstance)

{

appInstance.addLiveStreamPacketizerListener(new LiveActionNotify(appInstance));

getLogger().info(“ModuleCupertinoLiveAttachText.onAppStart[”+appInstance.getContextStr()+"]");

}

public void onAppStop(IApplicationInstance appInstance)

{

getLogger().info(“ModuleCupertinoLiveAttachText.onAppStop[”+appInstance.getContextStr()+"]");

}

}

Any help would be very much appreciated

Hi

I think you may be looking at the wrong header…

ID3 is designed for audio so I’d start my trying to make the headers match the example in order to rule out some potential issues.

Example :

In the example it says “ID3Frames id3HeaderAudio = cupertinoPacketizer.getID3FramesHeaderAudio();”

Your code says :

ID3Frames id3Header = cupertinoPacketizer.getID3FramesHeader();

I’d replace “id3Header” with “id3HeaderAudio” as a starting point but let us know how you get on.

Jason

Thanks for the reply.

I just tried what you suggested, but it didn’t make any difference- the metadata didn’t show up in the iOS app, and the ID3 tag is in the same place in the TS.