Adobe Animate AS3中NetStream在Windows投影仪多次视频切换后崩溃
AS3 NetStream切换视频导致Windows投影仪崩溃的解决方案
问题根源
你遇到的崩溃是内存泄漏导致的:原代码复用单个NetStream实例但未正确清理旧视频资源,Windows投影仪的Flash Player运行时对资源回收的限制比IDE更严格,多次切换后未释放的资源堆积引发内存溢出。具体问题点:
- 未调用
NetStream.close()释放当前播放的视频资源 - 未移除
NetStream的事件监听器,导致对象无法被垃圾回收(GC) - 未解绑Video对象与旧NetStream的关联
稳定运行的修复方案
以下是修改后的完整代码,核心是每次切换视频时彻底清理旧资源,再创建新的播放实例:
stop(); import flash.net.NetConnection; import flash.net.NetStream; import flash.net.NetStreamPlayOptions; import flash.net.NetStreamPlayTransitions; import flash.media.Video; import flash.events.MouseEvent; import flash.events.NetStatusEvent; import flash.text.TextField; import flash.text.TextFormat; import flash.display.Sprite; import flash.events.Event; // --- Debug Text Field --- var debugField:TextField = new TextField(); var debugFormat:TextFormat = new TextFormat("_sans", 14, 0x00FF00); debugField.defaultTextFormat = debugFormat; debugField.width = 300; debugField.height = stage.stageHeight; debugField.selectable = false; debugField.multiline = true; debugField.wordWrap = true; debugField.background = false; debugField.alpha = 0.7; debugField.x = stage.stageWidth - 300; debugField.y = 10; addChild(debugField); // --- Debug logging function --- function debug(msg:String):void { debugField.appendText(msg + "\n"); debugField.scrollV = debugField.maxScrollV; } // --- Base path for all videos --- const VIDEO_FOLDER:String = "Videos/"; // --- Video list --- var videoList:Array = ["video1.mp4", "video2.mp4", "video3.mp4"]; // 替换为你的视频文件名 var currentIndex:int = 0; // --- 全局播放对象引用 --- var nc:NetConnection; var ns:NetStream; var vid:Video = new Video(640, 360); addChild(vid); // --- 初始化第一个连接 --- initNetConnection(); // --- 初始化NetConnection --- function initNetConnection():void { nc = new NetConnection(); nc.connect(null); // 创建新的NetStream前先清理旧的 if(ns) { cleanUpNetStream(); } ns = new NetStream(nc); ns.client = {onMetaData: function():void{}}; // 必须实现onMetaData,避免警告 ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); vid.attachNetStream(ns); } // --- 清理NetStream资源 --- function cleanUpNetStream():void { if(ns) { ns.removeEventListener(NetStatusEvent.NET_STATUS, onNetStatus); ns.close(); // 关闭流,释放视频资源 ns = null; // 标记为null,帮助GC回收 } } // --- 播放视频函数 --- function playVideo(fileName:String):void { if(!fileName || fileName == "") { debug("无效的视频文件名"); return; } // 重新初始化连接(确保资源完全清理) initNetConnection(); var opts:NetStreamPlayOptions = new NetStreamPlayOptions(); opts.streamName = VIDEO_FOLDER + fileName; opts.transition = NetStreamPlayTransitions.SWITCH; opts.offset = -1; ns.play2(opts); debug("Playing: " + fileName); } // --- 按钮点击处理 --- function onStartClick(e:MouseEvent):void { playVideo(videoList[currentIndex]); debug("transitionNumber = " + currentIndex); currentIndex++; if (currentIndex >= videoList.length) { currentIndex = 0; // 循环切换 } } StartBtn.addEventListener(MouseEvent.CLICK, onStartClick); // --- 网络状态回调 --- function onNetStatus(e:NetStatusEvent):void { var code:String = e.info.code; trace("NetStatus: " + code); debug("NetStatus: " + code); // 可选:处理播放结束事件 if(code == "NetStream.Play.Stop") { debug("视频播放结束"); } } // --- 程序退出时清理资源 --- stage.addEventListener(Event.EXITING, onExiting); function onExiting(e:Event):void { cleanUpNetStream(); if(nc) { nc.close(); nc = null; } }
关键修改说明
- 添加
cleanUpNetStream()函数:负责关闭流、移除事件监听器、置空引用,确保资源被GC回收 - 每次切换视频时重新初始化
NetConnection和NetStream,避免旧资源残留 - 实现
ns.client.onMetaData:避免运行时警告,同时确保NetStream正常工作 - 添加程序退出时的资源清理逻辑,进一步防止泄漏
额外注意事项
- 确保视频文件路径正确,Windows投影仪的相对路径是从exe文件所在目录开始计算
- 测试时可以打开任务管理器观察内存占用,修复后内存应该不会持续上涨
- 若仍有问题,检查视频文件的编码格式,确保Flash Player支持(推荐H.264/AAC编码的MP4)
内容的提问来源于stack exchange,提问作者Adam Day-Williams
相关产品推荐
相关产品推荐

