WOWZA到IOS – 如何生活stream

到目前为止,我几乎开发了一个闪存空气IOS应用程序,我已经完成了50%。 我得到了所有现场stream媒体与RED5媒体服务器的工作,但当我发现iPhone摄像头正在显示90度,所以stream被发送并保存到RED5服务器也被logging90度来到死胡同。 我甚至在Stack Overflow上在线阅读了很多文章,这是一个已知的Bug。 不知道什么时候这将被修复。 我也尝试了一些ANE Air原生扩展,这将在我的Air App中工作相机旋转,这些是DiaDraw和StarlingCamera ANE,但无法在网上find任何信息教程,所以无法使其工作。

Flash的Adobe AIR的IOS代码连接到RED5服务器,并显示达到iPhone摄像头是90度:

import flash.display.DisplayObject; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.ActivityEvent; import flash.events.MouseEvent; import flash.media.Camera; import flash.media.Video; import flash.events.NetStatusEvent; import flash.net.NetStream; import flash.net.NetConnection; var nc:NetConnection; var cam:Camera; var vid:Video; var nsOut:NetStream; var nsIn:NetStream; // support autoOrients stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; cam = Camera.getCamera(); cam.setMode(320, 300, 25); cam.setQuality(0,100); if (!cam) { txt.text ="No camera is installed."; } else { nc = new NetConnection(); nc.connect("rtmp://192.168.1.5/RED5Hugt"); nc.addEventListener(NetStatusEvent.NET_STATUS,getStream); nc.client = this; //connectCamera(); } function getStream(e:NetStatusEvent):void { connectCamera(); nsIn = new NetStream(nc); nsOut = new NetStream(nc); vid.attachNetStream(nsIn); nsIn.play("tester"); nsOut=new NetStream(nc); netOut.attachAudio(mic); nsOut.attachCamera(cam); nsOut.publish("tester", "live"); // add click event to record button // add event for stage video render state } function connectCamera():void { vid = new Video(); vid.width = cam.width; vid.height = cam.height; vid.x = 0; vid.y = 0; vid.attachCamera(cam); addChild(vid); //stage.addEventListener(MouseEvent.CLICK, clickHandler); } function clickHandler(e:MouseEvent):void { return; switch (cam.width) { case 160: cam.setMode(320, 240, 10); break; case 320: cam.setMode(640, 480, 5); break; default: cam.setMode(160, 120, 15); break; } removeChild(vid); connectCamera(); } 

RED5服务器代码:

 package com; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import org.red5.server.adapter.ApplicationAdapter; import org.red5.server.adapter.MultiThreadedApplicationAdapter; import org.red5.server.api.IClient; import org.red5.server.api.IConnection; import org.red5.server.api.Red5; import org.red5.server.api.scope.IScope; import org.red5.server.api.service.IPendingServiceCall; import org.red5.server.api.service.IPendingServiceCallback; import org.red5.server.api.service.IServiceCapableConnection; import org.red5.server.api.service.IServiceHandlerProvider; import org.red5.server.api.stream.IBroadcastStream; import org.red5.server.api.stream.IServerStream; import org.red5.server.api.stream.support.SimplePlayItem; import org.red5.server.api.stream.support.StreamUtils; import org.red5.server.stream.ClientBroadcastStream; import org.red5.server.stream.RecordingListener; import static java.lang.System.*; public class Application extends MultiThreadedApplicationAdapter{ //private static final Log log = LogFactory.getLog( Application.class ); private IBroadcastStream serverStream; @Override public boolean appStart(IScope scope) { if(!super.appStart(scope)) { return false; } else { super.appStart(scope); return true; } } @Override public void appStop(IScope scope) { } //User connecting/disconnecting to/from application @Override public boolean appConnect(IConnection connection, Object[] parameters) { super.appConnect(connection, parameters); //connection.getClient().setAttribute("userName", parameters[0]); return true; } @Override public void appDisconnect(IConnection connection) { super.appDisconnect(connection); } //User joining/leaving scope @Override public boolean appJoin(IClient client, IScope scope) { super.appJoin(client, scope); return true; } @Override public void appLeave(IClient client, IScope scope) { super.appLeave(client,scope); } public boolean connect(IConnection conn, IScope scope, Object[] params) { super.connect(conn, scope, params); return true; } } 

所以然后我决定本地stream,并且我在Objective-C中使用了Media和CommLib库,并且发现了这个代码,我把它粘贴到了Pastebin上,因为在粘贴的时候有太多的代码需要编辑:

这是成功连接到另一台PC上运行的RED5 Java应用程序适配器的RTMP CLIENT。

http://pastebin.com/0KQvTL0b

当使用Xcode运行RTMP客户端时,该应用程序实时stream式传输,但是每隔几秒钟,audio就会出现故障,我找不到任何可以解决此问题的事情,也许我需要更改一些代码,但是我发现这个RTMP CLIENT代码在线,修改了Stream Name和RTMP Url以指向RED5服务器上的应用程序。

为什么audio不停地闪烁。 所以现在我想给WOWZA媒体服务器一个去。

到目前为止,我下载了Wowza Media Server,然后安装了Eclipse。 一旦安装了Eclipse,我就安装了我在Eclipse中安装的Wowza IDE,但确保在安装Wowza IDE之前先安装Wowza Media Server。

然后我发现一些在线的代码是在Wowza服务器上运行的服务器,新的Wowza服务器运行在浏览器中,我试图在terminal中运行这个代码,但不能运行,因为它一直说“操作无法运行“在terminal。

这是我用于服务器的代码:

 package com; import com.wowza.wms.application.*; import com.wowza.wms.amf.*; import com.wowza.wms.client.*; import com.wowza.wms.module.*; import com.wowza.wms.request.*; import com.wowza.wms.stream.*; import com.wowza.wms.rtp.model.*; import com.wowza.wms.httpstreamer.model.*; import com.wowza.wms.httpstreamer.cupertinostreaming.httpstreamer.*; import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.*; public class RED5Hugt extends ModuleBase { public void doSomething(IClient client, RequestFunction function, AMFDataList params) { getLogger().info("doSomething"); sendResult(client, params, "Hello Wowza"); } public void onAppStart(IApplicationInstance appInstance) { String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName(); getLogger().info("onAppStart: " + fullname); } public void onAppStop(IApplicationInstance appInstance) { String fullname = appInstance.getApplication().getName() + "/" + appInstance.getName(); getLogger().info("onAppStop: " + fullname); } public void onConnect(IClient client, RequestFunction function, AMFDataList params) { getLogger().info("onConnect: " + client.getClientId()); } public void onConnectAccept(IClient client) { getLogger().info("onConnectAccept: " + client.getClientId()); } public void onConnectReject(IClient client) { getLogger().info("onConnectReject: " + client.getClientId()); } public void onDisconnect(IClient client) { getLogger().info("onDisconnect: " + client.getClientId()); } public void onStreamCreate(IMediaStream stream) { getLogger().info("onStreamCreate: " + stream.getSrc()); } public void onStreamDestroy(IMediaStream stream) { getLogger().info("onStreamDestroy: " + stream.getSrc()); } } 

所以现在我运行RTMP客户端的Xcode项目,并发现RTMP客户端连接,但我没有得到实时stream。 只是想问我需要改变我的代码,以获得实时stream的工作?

还有我使用Adobe Air的IOS和使用RED5的经验,我应该采取这最后的路线,因为我不知道。 我已经研究了很多,真的想find知道如何从iPhone摄像头stream的无成本的方式。 我已经尝试了Adobe的IOS到RED5服务器,发现有一个已知的Bug,我已经尝试原生RED5,并发现audio故障所以是Wowza最好的赌注?

UPDATE

我在Xcode控制台中得到一个输出stream无法find,这里是输出:

 2014-07-30 13:33:06.246 RTMPStreamComeback[340:4003] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = MediaStreamPlayer, 4 = NetStream.Play.StreamNotFound 

我已经设置了UpStream名称“tester”和DownStream名称“tester”

更新

stream现在工作,我发现这个教程在线,发现我需要包括Application.xml和configuration文件。 这里是教程:

 https://www.youtube.com/watch?v=XoojcVfdHWg 

但是,就像RED5一样,Audio似乎也出现了问题,但是除了audio之外,audiostream不会被打乱。

我怎样才能解决这个问题?

这是Xcode的踪迹:

  2014-07-30 15:19:48.296 RTMPStreamComeback[397:60b] connectControl: host = rtmp://192.168.1.4:1935/RED5Hugt 2014-07-30 15:19:49.325 RTMPStreamComeback[397:60b] Video encoding is initialized: bit_rate = 272000, rc_max_rate = 0, rc_min_rate = 0, qmin=2, qmax=31, qcompress=0.500000 2014-07-30 15:19:49.334 RTMPStreamComeback[397:60b] AudioCodec: codecID = 86050, codecType = 42, bitRate = 16000, _sampleBytes = 4 encoder supports the sample formats: flt, audio codec best options: sample_rate = 44100 2014-07-30 15:19:49.340 RTMPStreamComeback[397:60b] audio codec context: codec_type = 1, sample_fmt = flt, bit_rate = 16000, sample_rate = 16000, channels = 1, frame_bits = 4, channel_layout = 0, frame_size = 0, buffer_size = 256 2014-07-30 15:19:49.344 RTMPStreamComeback[397:60b] initVideoCapture -> preset AVCaptureSessionPresetLow is supported, orientation = 3 2014-07-30 15:19:49.414 RTMPStreamComeback[397:60b] BroadcastStreamClient STREAM ----> name: tester, type: 2, [socket retainCount] = 3 2014-07-30 15:19:49.789 RTMPStreamComeback[397:60b] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = BroadcastStreamClient, 1 = RTMP.Client.isConnected 2014-07-30 15:19:49.831 RTMPStreamComeback[397:3f03] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = BroadcastStreamClient, 2 = RTMP.Client.Stream.isCreated 2014-07-30 15:19:50.585 RTMPStreamComeback[397:3f03] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = BroadcastStreamClient, 3 = NetStream.Publish.Start [flv @ 0x1883d000] Error, Invalid timestamp=0, last=0 [flv @ 0x1883d000] Error, Invalid timestamp=0, last=0 [flv @ 0x1883d000] Error, Invalid timestamp=0, last=0 2014-07-30 15:20:01.677 RTMPStreamComeback[397:60b] publishControl: stream = slavav 2014-07-30 15:20:01.680 RTMPStreamComeback[397:60b] NellyMoserDecoder -> audio codec context: codec_type = 1, sample_fmt = flt, bit_rate = 16000, sample_rate = 16000, channels = 1, frame_bits = 4, channel_layout = 0, frame_size = 0 2014-07-30 15:20:01.681 RTMPStreamComeback[397:60b] Set Player's Framework -> 'AudioUnit' 2014-07-30 15:20:01.685 RTMPStreamComeback[397:60b] VideoStream decoding is initialized: context->pix_fmt = 0, width = 0, height = 0 2014-07-30 15:20:01.689 RTMPStreamComeback[397:60b] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = MediaStreamPlayer, 1 = RTMP.Client.isConnected 2014-07-30 15:20:01.712 RTMPStreamComeback[397:3f03] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = MediaStreamPlayer, 2 = RTMP.Client.Stream.isCreated 2014-07-30 15:20:01.758 RTMPStreamComeback[397:3f03] $$$$$$ <MPIMediaStreamEvent> stateChangedEvent: sender = MediaStreamPlayer, 3 = NetStream.Play.Start [flv @ 0x1808c600] Bad picture start code [flv @ 0x1808c600] header damaged 2014-07-30 15:20:01.764 RTMPStreamComeback[397:3f03] VideoStream -> decodeFrame: (ERROR) got_packet = 0, processed_size = -1 [swscaler @ 0x2e38000] No accelerated colorspace conversion found from yuv420p to bgra. 2014-07-30 15:20:01.775 RTMPStreamComeback[397:7a03] MPAudioUnitEngine -> nextFrame: < NO PCM - WHITE NOISE > timestamp = 11192, dropWhiteNoise = 0 2014-07-30 15:20:01.799 RTMPStreamComeback[397:7a03] MPAudioUnitEngine -> nextFrame: < NO PCM - WHITE NOISE > timestamp = 11215, dropWhiteNoise = 0 2014-07-30 15:20:01.821 RTMPStreamComeback[397:7a03] MPAudioUnitEngine -> nextFrame: < NO PCM - WHITE NOISE > timestamp = 11238, dropWhiteNoise = 0 2014-07-30 15:20:01.845 RTMPStreamComeback[397:7a03] MPAudioUnitEngine -> nextFrame: < NO PCM - WHITE NOISE > timestamp = 11261, dropWhiteNoise = 0 2014-07-30 15:20:01.867 RTMPStreamComeback[397:7a03] MPAudioUnitEngine -> nextFrame: < NO PCM - WHITE NOISE > timestamp = 11284, dropWhiteNoise = 0 [flv @ 0x1808c600] Bad picture start code [flv @ 0x1808c600] header damaged 2014-07-30 15:20:01.888 RTMPStreamComeback[397:3f03] VideoStream -> decodeFrame: (ERROR) got_packet = 0, processed_size = -1 2014-07-30 15:23:31.088 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 320, dropWhiteNoise = 8600, pcm.remaining = 16036 2014-07-30 15:23:31.090 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 1024, dropWhiteNoise = 7576, pcm.remaining = 16036 2014-07-30 15:23:31.093 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 2048, dropWhiteNoise = 5528, pcm.remaining = 16036 2014-07-30 15:23:31.164 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 640, dropWhiteNoise = 4888, pcm.remaining = 16056 2014-07-30 15:23:31.219 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 128, dropWhiteNoise = 4760, pcm.remaining = 16028 2014-07-30 15:23:31.298 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 192, dropWhiteNoise = 4568, pcm.remaining = 16036 2014-07-30 15:23:31.604 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 128, dropWhiteNoise = 4440, pcm.remaining = 16048 2014-07-30 15:23:31.740 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 320, dropWhiteNoise = 4120, pcm.remaining = 16024 2014-07-30 15:23:32.296 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 192, dropWhiteNoise = 3928, pcm.remaining = 16008 2014-07-30 15:24:47.575 RTMPStreamComeback[397:3f03] MPAudioUnitEngine -> dropPcm: *** DROPPED = 64, dropWhiteNoise = 3864, pcm.remaining = 16000 

这些是audio和video格式的默认设置:默认stream媒体设置如下所示:

 Audio: codec - Nelly Mozer 16KHz, mono bitrate - 128000 Video: codec - H.263 (Sorenson) bitrate - 200000 resolution - 192x144px fps = 25 intra frame - 10 

还build议:

 Currently the library does not provide an instrument to control the stream quality. This is planned for a future release. 

所以我不认为这是可以改变audiostream格式