Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Multiple Audio/Video Streams on ONE parcel at the same time?

Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
09-07-2007 21:33
Hello.

I have been researching using multiple audio/video streams at the same time on ONE parcel of land. I have seen the post here: /54/86/204389/1.html
and I have investigated Silver Streams Network...but, both haven't really answered my question. It seems it's possible. Obviously, SSN has done it will video (still awaiting a reply from them about audio). I'm am wondering if anyone here...has ideas how it was done? Have you done this? The range factor that SSN has mentioned in their documents is important. Let me know...I appreciate it! Thanks.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
09-07-2007 21:44
llParcelMediaCommandList can take a parameter named PARCEL_MEDIA_COMMAND_AGENT, which allows the script to specify a video stream URL per-agent, even on the same parcel. Audio streams, however, can only be set per-parcel, via either the parcel's media tab, or script, using llSetParcelMusicURL.

lslwiki.net/lslwiki/wakka.php?wakka=llParcelMediaCommandList
lslwiki.net/lslwiki/wakka.php?wakka=llSetParcelMusicURL
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
09-08-2007 08:47
Deanna, are you sure that allows for specifying a different URL per agent? I believe the last call that contains a URL will set the URL for the entire parcel.

It IS possible to have multiple videos showing on the same parcel, sort of. You use one of the lesser-known formats that quicktime supports, called SMIL, which is an xml format that allows you to describe the display of multiple audio/video items all together, ie side by side or one after the other. Quicktime in SL can handle this fine, so then you just use texture repeats/offsets to split the video up onto multiple screens.
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
09-08-2007 20:23
From: Lex Neva
Deanna, are you sure that allows for specifying a different URL per agent? I believe the last call that contains a URL will set the URL for the entire parcel.

Nope. If a Parcel Media Command List contains PARCEL_MEDIA_COMMAND_AGENT, then the parcel's video stream URL, as seen on the media tab, is unaffected. In fact, the same goes for a media texture assigned thusly. So you could even have different users viewing different video streams which replace different textures, all on the same parcel.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
09-09-2007 08:13
From: Deanna Trollop
Nope. If a Parcel Media Command List contains PARCEL_MEDIA_COMMAND_AGENT, then the parcel's video stream URL, as seen on the media tab, is unaffected. In fact, the same goes for a media texture assigned thusly. So you could even have different users viewing different video streams which replace different textures, all on the same parcel.


Hmmmmm, this opens up some interesting possibilities!
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-10-2007 09:20
After reading this, I built a radio that plays different streams for everyone who operates it...

quite nice, especially, when you're renting houses and want to offer individual streams to every tenant...

I was thinking about making an iPod as well (I already have the dummy of it *lol*), but it would stop working when one moves out of the own land... so it's kinda useless...

But the aforementioned technique works perfect... :)
Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
Hi guys
09-10-2007 09:33
Haruki. Great. I've been having problems building my own radio streamer using this technique...I'm almost there...but, just can't get it to work. Any chance posting your code here, or sending it directly to me? I would appreciate it! Thanks!
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-10-2007 11:16
hmmmm ... :) I could offer you, to buy one in my store... *lol*

But since everyone's so helpful in here, I post the code anyway...

it's pretty uncommented though... hope you can read it...

This Code reads a notecard named «mystreams» where the Names and URLs of the streams are stored.
The Notecard has the form:

StreamName>URL

The StreamName will be whispered on channel 0 when an AV changes the station.

StreamName and URL are separated by a greater-than-sign (>;)

It needs the full path to the listen.pls

e.g. : Chromanova> 85.25.86.69:8300/listen.pls

The «http://» is added by the script

The script awaits linked messages from the start/stop/previous/next-buttons in the radio (make 4 linked buttons and send a llMessageLinked to the root prim sending start/stop/prev/next as the message)

Have fun with it... :)

CODE


list streams;
list stream_names;

key media_texture = "857ee732-c255-535c-bff9-9618a4eea03e"; // Copy the Asset UUID from the Texture that you want to use for the stream.

integer total_streams;
integer act_stream;

integer g_line;
key g_request;

string g_card;

init()
{
g_line = 0;
streams = [];
stream_names = [];
g_card = "mystreams";

llWhisper(0, "Reading configuration Notecard - be patient!");

g_request = llGetNotecardLine(g_card, g_line);
}

default
{
state_entry()
{
init();
}

changed(integer change)
{
if(change & CHANGED_INVENTORY)
{
// re-read the notecard

init();
}
}

dataserver(key queryid, string data)
{
list dummy;
integer show_line;

if(queryid == g_request)
{
show_line = g_line + 1;

llSetText("Reading configuration Notecard #" + (string)show_line, <255,255,255>, 1.0);

if(data != EOF)
{
if(llGetSubString(data, 0, 0) != "#" && llStringTrim(data, STRING_TRIM) != "")
{
dummy = llParseString2List(data, [">"], []);

streams += [llStringTrim(llList2String(dummy, 1), STRING_TRIM)];
stream_names += [llStringTrim(llList2String(dummy, 0), STRING_TRIM)];
//llWhisper(0, "Adding '" + llStringTrim(llList2String(dummy, 0), STRING_TRIM) + "' to the Stream-List");
}

g_line++;
g_request = llGetNotecardLine(g_card, g_line);
}
else
{
total_streams = llGetListLength(streams);
llWhisper(0, "Added " + (string)llGetListLength(streams) + " Streams/Playlists to the Radio -> Ready to play");
state play_it;
}
}
}

on_rez(integer blah)
{
llResetScript();
}
}

state play_it
{
state_entry()
{
act_stream = 0;

llSetText("", <255,255,255>, 1.0);

//PARCEL_MEDIA_COMMAND_URL

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream)]);
}

changed(integer change)
{
if(change & CHANGED_INVENTORY)
{
// re-read the notecard
state default;
}
}

link_message(integer sender, integer num, string str, key id)
{
if(str == "play")
{
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_PLAY]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "prev")
{
if(act_stream == 0)
{
act_stream = total_streams - 1;
}
else
{
act_stream--;
}

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream)]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "next")
{
if(act_stream == total_streams - 1)
{
act_stream = 0;
}
else
{
act_stream++;
}

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream)]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "stop")
{
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_STOP]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Stopped playing for agent " + llKey2Name(id));
}


}
}


Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
Thank You !
09-12-2007 18:58
Haruki - you rock!

I appreciate your help. For some reason the forum's auto notify didn't tell me until now that you replied. Sorry for the delay....

Better hide your post now...so, anyone won't be off to sell your ipod idea... ;)
Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
follow up question
09-13-2007 09:23
Hi. Well, I've been beta testing your code and I can't get it to work on group own land for two different avatars at once. Question: did you get it to work for multiple avatars listening to different streams from different script-abled prims? IF so, how? I can't seem too...when one avatar clicks to change the station or stop/play...all the other scripts are changed/stopped etc. on the group owned land. I've tried not deeded and deeded the prims to the group...same things happens both times. I am just really stupid...or is there something stopping this from working on group land? I appreciate any help. thanks!
Deanna Trollop
BZ Enterprises
Join date: 30 Jan 2006
Posts: 671
09-13-2007 10:47
From: Seann Sands
did you get it to work for multiple avatars listening to different streams from different script-abled prims?
Separate streams for different avatars on the same parcel only works for *video* streams. Audio streams are still limited to one-per-parcel.
Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
even when playing them via quicktime?
09-13-2007 11:41
Hi again. Deanna...is this still true...when playing the audio via the quicktime plugin...using the video (media) preference? Shouldn't it work like a video? I know the audio stream land settings won't work as you mentioned...but, I was hoping to use the media quicktime to stream audio as well as video (using quicktime comp. audio). Thank you for help!
Rock Ryder
Registered User
Join date: 6 Oct 2006
Posts: 384
09-13-2007 12:05
From: Deanna Trollop
Separate streams for different avatars on the same parcel only works for *video* streams. Audio streams are still limited to one-per-parcel.


Not strictly true. The term 'video' in SL means a composite signal comprising both a video component and an audio component. I have had streaming and direct linking 'video' to my parcels for some time, with the video part of the signal being set to a fixed image. This produced a composite signal that is only marginally greater in size to a standard mp3. Using this technique I can have multiple 'audio' streams to my parcel ( I just ignore the fixed image, which is on a tiny prim and is invisible anyway.

Rock
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-13-2007 13:03
Hi Sean

ups...? I actually tried it with my AV and my alt - and it worked...

But I'll test it again then... maybe there's something wrong with the code...? (not enough beta testing, maybe...)

I'll get back to you asap...

[edit]

man - I just saw, that I pasted an version of the script, that doesn't work... :(

I'll post the working one in a sec... :)
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-13-2007 13:27
here it goes:

CODE


list streams;
list stream_names;

key media_texture = "857ee732-c255-535c-bff9-9618a4eea03e";

integer total_streams;
integer act_stream;

integer g_line;
key g_request;

string g_card;

init()
{
g_line = 0;
streams = [];
stream_names = [];
g_card = "mystreams";

llWhisper(0, "Reading configuration Notecard - be patient!");

g_request = llGetNotecardLine(g_card, g_line);
}

default
{
state_entry()
{
init();
}

changed(integer change)
{
if(change & CHANGED_INVENTORY)
{
// re-read the notecard

init();
}
}

dataserver(key queryid, string data)
{
list dummy;
integer show_line;

if(queryid == g_request)
{
show_line = g_line + 1;

llSetText("Reading configuration Notecard #" + (string)show_line, <255,255,255>, 1.0);

if(data != EOF)
{
if(llGetSubString(data, 0, 0) != "#" && llStringTrim(data, STRING_TRIM) != "")
{
dummy = llParseString2List(data, [">"], []);

streams += [llStringTrim(llList2String(dummy, 1), STRING_TRIM)];
stream_names += [llStringTrim(llList2String(dummy, 0), STRING_TRIM)];
//llWhisper(0, "Adding '" + llStringTrim(llList2String(dummy, 1), STRING_TRIM) + "' to the Stream-List");
}

g_line++;
g_request = llGetNotecardLine(g_card, g_line);
}
else
{
total_streams = llGetListLength(streams);
llWhisper(0, "Added " + (string)llGetListLength(streams) + " Streams/Playlists to the Radio -> Ready to play");
state play_it;
}
}
}

on_rez(integer blah)
{
llResetScript();
}
}

state play_it
{
state_entry()
{
act_stream = 0;

llSetText("", <255,255,255>, 1.0);

//PARCEL_MEDIA_COMMAND_URL

//llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream)]);
}

changed(integer change)
{
if(change & CHANGED_INVENTORY)
{
// re-read the notecard
state default;
}
}

link_message(integer sender, integer num, string str, key id)
{
if(str == "play")
{
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_PLAY]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "prev")
{
if(act_stream == 0)
{
act_stream = total_streams - 1;
}
else
{
act_stream--;
}

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream), PARCEL_MEDIA_COMMAND_PLAY]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "next")
{
if(act_stream == total_streams - 1)
{
act_stream = 0;
}
else
{
act_stream++;
}

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream), PARCEL_MEDIA_COMMAND_PLAY]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Playing '" + llList2String(stream_names, act_stream) + "' for agent " + llKey2Name(id));
}

if(str == "stop")
{
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_STOP]);
list Info = llParcelMediaQuery([PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TEXTURE]);
llWhisper(0, "Stopped playing for agent " + llKey2Name(id));
}


}
}




The issue was this piece of code:

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, id, PARCEL_MEDIA_COMMAND_URL, "http://" + llList2String(streams, act_stream), PARCEL_MEDIA_COMMAND_PLAY]);

... in the prev/next/stop-commands. In the first version, the commands for the Agent were missing, thus, the stream stops/skips for every agent that's listening...

Try it - hope it'll work this time... sorry... :)
Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
Hi...still not working
09-13-2007 16:51
Haruki,

I just tested your new script...and it's still changing both prims I have script-enabled in the same group parcel of land, making it "hearable" by both avatars (I can run two clients at once to test this). I've deeded the prims to the group. You got this script to work for two avatars hearing (or seeing) the different media and the same time on the same parcel? IF so...I'm very interested on how you did....and wondering what I'm doing wrong. Could it be group land? Or the way I'm calling the script in the linked prims? Or both?

Rock, how did you do this? Willing to share? :)

thanks in advance...
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-13-2007 23:40
hmmm - you're talking about two prims... guess that might be the quirk - I only tested it with one object. The two AVs both klick on the same device and this worked...
I never tested whether I can run two objects at once... Guess I'll have to do that...

I get back to ya...

[edit]

Ok - I tested it with two devices now. One operated by my av, the other one by my alt... and it works - two different streams.

Maybe it has something to do with permissions...

The Notecard in it has modify/copy perms. The Object itself has 'next owner can modify'-perms.

It might be interesting, whether my objects work for you - you can find them in my demo-shop @ Golden Business Area -> 48,232,21

The setup of the object is:

the root prim with the script and the notecard in it and then 4 linked child objects (prev/stop/play/next)...

You might wanna give me a copy of your object in world (with full perms) so I could have a look at it and maybe find the difference...
(might take a moment until I have the time to look at it though...)
Seann Sands
Registered User
Join date: 8 Mar 2007
Posts: 49
thanks.
09-14-2007 13:27
Hi Haruki,

Will do. I'll work on it this weekend. Thank you for you help!
Garth Bellman
Registered User
Join date: 6 Oct 2006
Posts: 28
Separate stream causing crash
09-15-2007 15:13
Hi,

I'm trying something similar with pls streams only, and each time I use it its okay, but when someone else uses it, it crashes them out. Anyone else seen this behaviour?

Cheers,
Garth
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-15-2007 17:23
I'm experiencing exactly the same right now... :(

I have several working items... at the place where my shop is, I have one working as well... this land is divided into serveral parcels... when I rezz another item just beside the one that's working, the new item works as well. But as soon as I rezz it in a different parcel (on the same land!), my AV crashes...

Pretty strange and I'm working on that...

[edit]

I found out, that when I move the second object too far away from the first one, the crash occurs... It somehow seems, that the two objects are somehow connected. I found out, that when I open the notecard of the first object and then open notecard of the 2nd, no 2nd notecard opens - it seems as if I open the same notecard with both objects...
It obviously depends on the parcel I'm in... it works in the parcel, where I have my shop - but not in the one nearby. When I activate the debug-console, I get the message: convertImageAndLoadUrl: MEDIA> unable to load... the two parcels do have similar setups... I can't find a difference...
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
Solution to crashes
09-16-2007 03:36
OK, I think I found the caveat... :)

On the parcel where the Radio worked, i had «Auto Scale Content»-Box in the Media-Tab in the Land info checked.
On the parcel, where I crashed as soon as I clicked on the radio, I didn't have this box checked... This «kinda»*makes sense, since the media I'm playing has no dimensions at all because it's just a stream and not a video. So when the box is unchecked and the stream is attempted to be played, the Client tries to set the dimensions of the video, which are NULL (I guess). This might cause a division by zero somewhere which causes the client to crash. With the box checked, the Client just sets the dimensions to zero (which they are) and then plays the stream...
This is just a guess, though, but it could most likely be the problem...
Garth Bellman
Registered User
Join date: 6 Oct 2006
Posts: 28
09-16-2007 12:10
Hi Haruki,

I will try this with my setup tonight and post what I find. It seems plausible :)

Garth
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-16-2007 14:38
Plausible yes - but still kinda weird, hard to find and if my assumption is right, I would at least expect some kind of error-message/warning and not a complete crash of the client...

Hope it'll fix your problem as well :)
Garth Bellman
Registered User
Join date: 6 Oct 2006
Posts: 28
Fixed
10-01-2007 04:02
Unsetting the autoscale worked for me too with just audio streams. It no longer kills other avatars. Good spot!!
Shirley Marquez
Ethical SLut
Join date: 28 Oct 2005
Posts: 788
10-01-2007 07:42
From: Rock Ryder
Not strictly true. The term 'video' in SL means a composite signal comprising both a video component and an audio component. I have had streaming and direct linking 'video' to my parcels for some time, with the video part of the signal being set to a fixed image. This produced a composite signal that is only marginally greater in size to a standard mp3.


Sounds like an interesting technique! Since audio in QuickTime can be encoded with AAC, which is more bit-efficient than MP3, you might be able to produce a stream which is actually SMALLER than an MP3 and still sounds good.