Netstream 仅获取音频 (SoundMixer.computeSpectrum)

Netstream Get Audio Only (SoundMixer.computeSpectrum)

Netstream 仅作为声音?

我正在尝试将来自网络流的声音放入声音变量中,这样我就可以像在 this tutorial 中那样对其进行可视化。 Adobe ActionScript 3.0 * 访问原始声音数据

问题是,搜索结果只找到如何将视频附加到视频对象,而不是声音对象。

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..
    }

该示例使用 SoundMixer.computeSpectrum 因此只要您正在播放的 NetStream 不是 RTMP 流,一切都可以正常工作。

this method cannot be used to extract data from RTMP streams

假设您没有使用 RTMP 流,下面是一个使用 NetStream vs Sound 的示例,我将其覆盖在正在播放的视频顶部的 waveform

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);
        }

    }
}

为了能够将 SoundMixer.computeSpectrum() 与 RTMP 流的音频一起使用,您应该首先在服务器端启用对音频原始数据的访问,如下所示:

对于 Adob​​e/Flash 媒体服务器 (AMS/FMS):

Application.xml :

<Application> 

    <!-- ... -->

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

    <!-- ... -->

</Application>

或使用Main.asc:

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

    p_client.audioSampleAccess = "/";

    // ...      
}

对于 Wowza 媒体服务器:

Application.xml :

<Application>

    <!-- ... -->

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

    <!-- ... -->

</Application>

对于 RED5:

red5-web.xml :

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

然后您只需像往常一样播放您的流,对于声波数据的图形表示,您可以使用 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 这里是 AMS / FMS 提供的 FLV 视频文件。您当然可以使用任何类型的受支持的视频或音频文件(MP4、MP3 等)。

上面的代码给你这样的东西:

希望能帮到你。