Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crackling sound on NetStream stop #3260

Open
itlancer opened this issue May 21, 2024 · 1 comment
Open

Crackling sound on NetStream stop #3260

itlancer opened this issue May 21, 2024 · 1 comment
Labels

Comments

@itlancer
Copy link

itlancer commented May 21, 2024

Problem Description

NetStream stop via NetStream::close() or NetStream::dispose() cause sound crackling.
May be under hood AIR should send some extra data at NetStream::close() or NetStream::dispose() to audio decoder to prevent such behavior.

Reproduced with multiple AIR versions, even with latest AIR 51.0.1.1 with multiple different platforms (Windows, macOS, Android, iOS) with different devices, applications and videos.
Same issue in all cases. But with some audio devices (or audio drivers) and some videos/sound it not noticeable.
There is no such issue using many other (non-AIR) video/audio applications, especially wich uses ffmpeg.
Setting SoundTransform::volume to 0 just before NetStream::close() or NetStream::dispose() didn't help.
Playing with NetStreamAppendBytesAction.END_SEQUENCE just before NetStream::close() or NetStream::dispose() didn't help.
Didn't test with FLV videos.
Didn't test with Sound.

Related issues:
#1939
#224
#211
#202
#155
#15

Steps to Reproduce

Launch application with code below. It just play video with audio in a loop. Click anywhere on stage to restart video (it will be stopped and new one started).
You need to click in a "correct" moment to hear crackling noticeable and clear. Please take a look at demonstration video below.

Application example with sources and video sample attached.
netstream_stop_crackling_bug.zip

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.events.NetStatusEvent;
	import flash.desktop.SystemIdleMode;
	import flash.filesystem.File;
	import flash.events.MouseEvent;
	
	public class NetStreamStopCracklingBug extends Sprite {
		private var nc:NetConnection;
		private var ns:NetStream;
		private var video:Video = new Video(640, 480);
		
		public function NetStreamStopCracklingBug() {
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			addChild(video);
			
			stage.addEventListener(MouseEvent.CLICK, click);
			
			restartVideo();
		}
		
		private function click(e:MouseEvent):void {
			trace("click");
			restartVideo();
		}
	
		private function restartVideo():void {
			if (ns != null){
				ns.removeEventListener(NetStatusEvent.NET_STATUS, nsHandler);
				
				//These two lines cause audio crackling
				ns.close();
				ns.dispose();
			}
			if (nc != null){
				nc.removeEventListener(NetStatusEvent.NET_STATUS, ncHandler);
				nc.close();
			}
			
			nc = new NetConnection();
			nc.addEventListener(NetStatusEvent.NET_STATUS, ncHandler);
			nc.connect(null);
		}
		
		private function ncHandler(e:NetStatusEvent):void {
			if (e.info.code == "NetConnection.Connect.Success"){
				ns = new NetStream(nc);
				ns.client = {onMetaData:getMeta};
				ns.addEventListener(NetStatusEvent.NET_STATUS, nsHandler);
				video.attachNetStream(ns);
				
				ns.play("video.mp4");
			}
		}

		private function nsHandler(e:NetStatusEvent):void {
			trace(e.info.code);
			if (e.info.code == "NetStream.Play.Stop"){
				ns.play("video.mp4");
			}
		}

		private function getMeta(mdata:Object):void { }
		
	}
}

Actual Result:
Audio crackling at video restart (NetStream::close() or NetStream::dispose() call).
Video demonstration:

demonstration.mp4

Expected Result:
No audio crackling at video restart (or stop).

Known Workarounds

  1. After video playback change volume to mute (via soundTransform), wait ~30 frames (via ENTER_FRAME) and only after call NetStream::dispose().
  2. Write your own native extension to play video.
@itlancer
Copy link
Author

Found workaround.
After video playback change volume to mute (via soundTransform), wait ~30 frames (via ENTER_FRAME) and only after call NetStream::dispose().
But for iOS it doesn't work. Seems this issue #15 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant