0

Netstream As sound only?

I'm trying to put the sound coming from a netstream into a Sound variable so I can visualize it like in this tutorial. Adobe ActionScript 3.0 * Accessing raw sound data

Problem is, search results only find how to attach a video to a video object, and not a sound object.

private function handleAccept(e:MouseEvent):void 
    {
    myNS.attachAudio(Microphone.getEnhancedMicrophone(0));
    myNS.publish("audio");

    var s:Sound = new Sound(theirNS.play("audio"));//??
    s.play(); 

    //Custom tranformation ahead..
    }
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
sfxworks
  • 1,031
  • 8
  • 27

2 Answers2

1

That example uses SoundMixer.computeSpectrum and thus as long as the NetStream you are playing is not an RTMP stream, everything will work fine.

this method cannot be used to extract data from RTMP streams

Assuming you are not using a RTMP stream, here is an example using NetStream vs Sound that I have that overlays the waveform on top on the video that is playing:

enter image description here

package {
    import flash.display.Graphics;
    import flash.events.Event;
    import flash.media.SoundMixer;
    import flash.display.Sprite;
    import flash.net.NetStream;
    import flash.net.NetConnection;
    import flash.utils.ByteArray;
    import flash.media.Video;

    public class Main extends Sprite {

        const PLOT_HEIGHT:int = 200;
        const CHANNEL_LENGTH:int = 256;
        private var bytes:ByteArray = new ByteArray();

        private var videoURL:String = "YourVideoURL";
        private var connection:NetConnection;
        private var video:Video = new Video();
        private var waveForm:Sprite = new Sprite();

        public function Main() {

            connection = new NetConnection();
            connection.connect(null);
            video.width = parent.stage.stageWidth;
            video.height = parent.stage.stageHeight;
            addChild(video);

            var stream:NetStream = new NetStream(connection);
            stream.client = new CustomClient();
            video.attachNetStream(stream);
            stream.play(videoURL);

            addChild(waveForm);
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        function onEnterFrame(event:Event):void {
            SoundMixer.computeSpectrum(bytes, false, 0);

            var g:Graphics = waveForm.graphics;

            g.clear();
            g.lineStyle(0, 0xffeeff);
            g.beginFill(0xeeffee);
            g.moveTo(0, PLOT_HEIGHT);

            var n:Number = 0;

            // left channel
            for (var i:int = 0; i < CHANNEL_LENGTH; i++) {
                n = (bytes.readFloat() * PLOT_HEIGHT);
                g.lineTo(i * 2, PLOT_HEIGHT - n);
            }
            g.lineTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT);
            g.endFill();

            // right channel
            g.lineStyle(0, 0xeeffee);
            g.beginFill(0xffeeff, 0.5);
            g.moveTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT);

            for (i = CHANNEL_LENGTH; i > 0; i--) {
                n = (bytes.readFloat() * PLOT_HEIGHT);
                g.lineTo(i * 2, PLOT_HEIGHT - n);
            }
            g.lineTo(0, PLOT_HEIGHT);
            g.endFill();
        }

        function onPlaybackComplete(event:Event) {
            removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

    }
}
SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • I don't agree with you about the point concerning the use of `SoundMixer.computeSpectrum()` with an RTMP stream because Adobe said, few lines after what you've mentioned, "... This method is supported over RTMP in Flash Player 9.0.115.0 and later and in Adobe AIR...", and I know that's working with an RTMP stream because I've used it in the past ... – akmozo Oct 26 '15 at 17:17
  • It is possible that the condition of support changed and now the docs are messed up, I know that DRM was a factor and thus there were restrictions on RTMP streams, RTMP bypassed a lot of internal classes so you could not 'pirate' the stream... I do not use RTMP streaming anymore, have not for many many many years, only adaptive H.264... – SushiHangover Oct 26 '15 at 17:58
  • I guess I should of phrased the question how to compute the sound spectrum from an rtmp stream. It's coming from another peer using adobe cirrus. I'll definitely save this though. – sfxworks Oct 27 '15 at 07:56
  • Have you tried the RTMP stream? I am just wondering if it works as @akmozo noted that the docs also say that it should work and which part of the docs are in error... – SushiHangover Oct 27 '15 at 08:03
1

To be able to use SoundMixer.computeSpectrum() with the audio of an RTMP stream, you should start by enabling the access to the audio raw data in the server side like this :

For Adobe / Flash Media Server ( AMS / FMS ) :

Application.xml :

<Application> 

    <!-- ... -->

    <Client>
        <Access>
            <AudioSampleAccess enabled="true">/</AudioSampleAccess>
        </Access>
    </Client>

    <!-- ... -->

</Application>

or using Main.asc :

application.onConnect = function( p_client, p_autoSenseBW )
{
    // ...

    p_client.audioSampleAccess = "/";

    // ...      
}

For Wowza Media Server :

Application.xml :

<Application>

    <!-- ... -->

    <Client>
        <Access>
            <StreamAudioSampleAccess>*</StreamAudioSampleAccess>
        </Access>
    </Client>

    <!-- ... -->

</Application>

For RED5 :

red5-web.xml :

<bean id="rtmpSampleAccess" class="org.red5.server.stream.RtmpSampleAccess">
    <property name="audioAllowed" value="true"/>
</bean> 

Then you have just to play your stream as you did usually and for the graphic representation of the sound wave data, you can use, for example, the example code available in the documentation page of SoundMixer.computeSpectrum() :

var server:String = 'rtmp://127.0.0.1/vod', stream:String = 'sample',
    nc:NetConnection, ns:NetStream, vd:Video,
    spectrum:Sprite, last_status:String = '';

nc = new NetConnection();
nc.connect(server);
nc.addEventListener(NetStatusEvent.NET_STATUS, on_NetStatus);
nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent): void {});

function on_NetStatus(e:NetStatusEvent):void
{
    var code:String = e.info.code;
    switch (code)
    {
        case 'NetConnection.Connect.Success' :

            ns = new NetStream(nc);
            ns.bufferTime = 3;
            ns.addEventListener(NetStatusEvent.NET_STATUS, on_NetStatus);
            ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, function(e:AsyncErrorEvent): void {});

            vd = new Video(320,180);
            vd.x = vd.y = 0;
            vd.attachNetStream(ns);
            addChild(vd);

            spectrum = new Sprite();
            spectrum.x = spectrum.y = 0;
            addChild(spectrum);

            ns.play(stream);

            break;

        case 'NetStream.Play.Start' :
            addEventListener(Event.ENTER_FRAME, on_EnterFrame);
            break;

        case 'NetStream.Buffer.Flush':          
            if(last_status == 'NetStream.Play.Stop'){
                removeEventListener(Event.ENTER_FRAME, on_EnterFrame);
            }
            break;
    }

    last_status = code;

}

function on_EnterFrame(event:Event):void
{
    var bytes:ByteArray = new ByteArray();
    const PLOT_HEIGHT:int = stage.stageHeight / 2;
    const CHANNEL_LENGTH:int = 256;

    SoundMixer.computeSpectrum(bytes, false, 0);

    var g:Graphics = spectrum.graphics;

    g.clear();

    g.lineStyle(0, 0xffffff);
    g.beginFill(0x00ff00);
    g.moveTo(0, PLOT_HEIGHT);

    var n:Number = 0;

    for (var i:int = 0; i < CHANNEL_LENGTH; i++)
    {
        n = (bytes.readFloat() * PLOT_HEIGHT);
        g.lineTo(i * 2, PLOT_HEIGHT - n);
    }

    g.lineTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT);
    g.endFill();

    g.lineStyle(0, 0xCC0066);
    g.beginFill(0xCC0066, 0.5);
    g.moveTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT);

    for (i = CHANNEL_LENGTH; i > 0; i--)
    {
        n = (bytes.readFloat() * PLOT_HEIGHT);
        g.lineTo(i * 2, PLOT_HEIGHT - n);
    }

    g.lineTo(0, PLOT_HEIGHT);
    g.endFill();
}

sample here is an FLV video file provided with AMS / FMS. You can of course use any kind of supported video or audio files ( MP4, MP3, ... ).

The above code gives you something like this :

Hope that can help.

akmozo
  • 9,829
  • 3
  • 28
  • 44
  • Is access of raw audio already enabled on [adobe cirrus](http://labs.adobe.com/technologies/cirrus/)? Would I have to do something to send over raw audio from the microphone, or is this already done? Adobe Cirrus is peer to peer, so I'm not fetching a rtmp stream from an Adobe / Flash Media Server. It's coming from another client. – sfxworks Oct 27 '15 at 10:49
  • @quantomworks I don't understand what you need exactly. If you want to do the same thing, as what I did, with your mic, take a look [here](http://blog.onebyonedesign.com/actionscript/digging-into-the-microphone-in-flash-player-10-1/) ... – akmozo Oct 27 '15 at 10:54
  • Sorry, I'll explain a little better. I'm using adobe air to connect to Cirrus. Any client that connects to cirrus will get a nearid. When one user wants to call another user, he will type in the remote user's nearid. They connect using the NetStream object created through a NetConnection class that is connected to adobe cirrus' server. What I want to do is be able to not only play their audio from the stream, but make a sound spectrum display generated from the remote user's voice that's coming from the NetStream object. – sfxworks Oct 27 '15 at 11:02
  • @quantomworks I don't know how Cirrus is working exactly, but I don't think that Adobe will give you the ability to access to the raw audio ... Try my code, in any case you won't loose any thing ... – akmozo Oct 27 '15 at 11:08
  • ! That's it! I got it! I'll use your code and instead of computing the spectrum on the recieving end, ill send over parameters for it using netstream.send based on the local audio from the sending user's mic! – sfxworks Oct 27 '15 at 11:25
  • Ah looks like I'd have to replay the audio from their microphone if I were to do that.. Hmm.. Good data here though. Will save and use for the future. – sfxworks Nov 01 '15 at 14:31