diff --git a/Configuration/UserConfig.cs b/Configuration/UserConfig.cs
index 0fc8b38a..6c982d3a 100644
--- a/Configuration/UserConfig.cs
+++ b/Configuration/UserConfig.cs
@@ -83,8 +83,8 @@ static UserConfig(){
         public Size CustomNotificationSize             { get; set; } = Size.Empty;
         public int NotificationScrollSpeed             { get; set; } = 100;
 
-        public int NotificationSoundVolume { get; set; } = 100;
         private string _notificationSoundPath;
+        private int _notificationSoundVolume = 100;
 
         public string CustomCefArgs         { get; set; } = null;
         public string CustomBrowserCSS      { get; set; } = null;
@@ -94,12 +94,18 @@ static UserConfig(){
 
         public bool IsCustomNotificationPositionSet => CustomNotificationPosition != ControlExtensions.InvisibleLocation;
         public bool IsCustomNotificationSizeSet => CustomNotificationSize != Size.Empty;
+        public bool IsCustomSoundNotificationSet => NotificationSoundPath != string.Empty;
 
         public TwitterUtils.ImageQuality TwitterImageQuality => BestImageQuality ? TwitterUtils.ImageQuality.Orig : TwitterUtils.ImageQuality.Default;
         
         public string NotificationSoundPath{
-            get => string.IsNullOrEmpty(_notificationSoundPath) ? string.Empty : _notificationSoundPath;
-            set => _notificationSoundPath = value;
+            get => _notificationSoundPath ?? string.Empty;
+            set => UpdatePropertyWithEvent(ref _notificationSoundPath, value, SoundNotificationChanged);
+        }
+        
+        public int NotificationSoundVolume{
+            get => _notificationSoundVolume;
+            set => UpdatePropertyWithEvent(ref _notificationSoundVolume, value, SoundNotificationChanged);
         }
 
         public bool MuteNotifications{
@@ -122,6 +128,7 @@ public TrayIcon.Behavior TrayBehavior{
         public event EventHandler MuteToggled;
         public event EventHandler ZoomLevelChanged;
         public event EventHandler TrayBehaviorChanged;
+        public event EventHandler SoundNotificationChanged;
 
         // END OF CONFIG
         
diff --git a/Core/Bridge/PropertyBridge.cs b/Core/Bridge/PropertyBridge.cs
index e43800c2..cfcbafdf 100644
--- a/Core/Bridge/PropertyBridge.cs
+++ b/Core/Bridge/PropertyBridge.cs
@@ -19,7 +19,6 @@ public static string GenerateScript(Environment environment){
                 build.Append("x.openSearchInFirstColumn=").Append(Bool(Program.UserConfig.OpenSearchInFirstColumn));
                 build.Append("x.keepLikeFollowDialogsOpen=").Append(Bool(Program.UserConfig.KeepLikeFollowDialogsOpen));
                 build.Append("x.muteNotifications=").Append(Bool(Program.UserConfig.MuteNotifications));
-                build.Append("x.hasCustomNotificationSound=").Append(Bool(Program.UserConfig.NotificationSoundPath.Length > 0));
                 build.Append("x.notificationMediaPreviews=").Append(Bool(Program.UserConfig.NotificationMediaPreviews));
                 build.Append("x.translationTarget=").Append(Str(Program.UserConfig.TranslationTarget));
             }
diff --git a/Core/Bridge/TweetDeckBridge.cs b/Core/Bridge/TweetDeckBridge.cs
index aa376266..48b95893 100644
--- a/Core/Bridge/TweetDeckBridge.cs
+++ b/Core/Bridge/TweetDeckBridge.cs
@@ -126,7 +126,7 @@ public void OnTweetPopup(string columnId, string chirpId, string columnName, str
         public void OnTweetSound(){
             form.InvokeAsyncSafe(() => {
                 form.OnTweetNotification();
-                form.PlayNotificationSound();
+                form.OnTweetSound();
             });
         }
 
diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index ed964d6c..0e437218 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -15,7 +15,6 @@
 using TweetDuck.Plugins;
 using TweetDuck.Plugins.Events;
 using TweetDuck.Updates;
-using TweetLib.Audio;
 
 namespace TweetDuck.Core{
     sealed partial class FormBrowser : Form{
@@ -50,7 +49,6 @@ public bool IsWaiting{
         private FormWindowState prevState;
         
         private TweetScreenshotManager notificationScreenshotManager;
-        private SoundNotification soundNotification;
         private VideoPlayer videoPlayer;
         private AnalyticsManager analytics;
 
@@ -82,7 +80,6 @@ public FormBrowser(UpdaterSettings updaterSettings){
                 contextMenu.Dispose();
 
                 notificationScreenshotManager?.Dispose();
-                soundNotification?.Dispose();
                 videoPlayer?.Dispose();
                 analytics?.Dispose();
             };
@@ -291,22 +288,6 @@ private void updates_UpdateDismissed(object sender, UpdateEventArgs e){
             });
         }
 
-        private void soundNotification_PlaybackError(object sender, PlaybackErrorEventArgs e){
-            e.Ignore = true;
-
-            using(FormMessage form = new FormMessage("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, MessageBoxIcon.Error)){
-                form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
-
-                Button btnOpenSettings = form.AddButton("View Options");
-                btnOpenSettings.Width += 16;
-                btnOpenSettings.Location = new Point(btnOpenSettings.Location.X-16, btnOpenSettings.Location.Y);
-
-                if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnOpenSettings){
-                    OpenSettings(typeof(TabSettingsSounds));
-                }
-            }
-        }
-
         protected override void WndProc(ref Message m){
             if (isLoaded && m.Msg == Program.WindowRestoreMessage){
                 if (WindowsUtils.CurrentProcessID == m.WParam.ToInt32()){
@@ -357,6 +338,10 @@ public void ReloadColumns(){
             browser.ReloadColumns();
         }
 
+        public void PlaySoundNotification(){
+            browser.PlaySoundNotification();
+        }
+
         public void ApplyROT13(){
             browser.ApplyROT13();
         }
@@ -459,19 +444,7 @@ public void OpenPlugins(){
             }
         }
 
-        public void PlayNotificationSound(){
-            if (Config.NotificationSoundPath.Length == 0){
-                return;
-            }
-
-            if (soundNotification == null){
-                soundNotification = new SoundNotification();
-                soundNotification.PlaybackError += soundNotification_PlaybackError;
-            }
-
-            soundNotification.SetVolume(Config.NotificationSoundVolume);
-            soundNotification.Play(Config.NotificationSoundPath);
-
+        public void OnTweetSound(){
             TriggerAnalyticsEvent(AnalyticsFile.Event.SoundNotification);
         }
 
diff --git a/Core/Notification/FormNotificationBase.cs b/Core/Notification/FormNotificationBase.cs
index 86b5c055..67e119a7 100644
--- a/Core/Notification/FormNotificationBase.cs
+++ b/Core/Notification/FormNotificationBase.cs
@@ -139,8 +139,7 @@ protected FormNotificationBase(FormBrowser owner, bool enableContextMenu){
 
             DpiScale = this.GetDPIScale();
 
-            DefaultResourceHandlerFactory handlerFactory = (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
-            handlerFactory.RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
+            browser.GetHandlerFactory().RegisterHandler(TwitterUtils.TweetDeckURL, this.resourceHandler);
 
             Controls.Add(browser);
 
diff --git a/Core/Notification/SoundNotification.cs b/Core/Notification/SoundNotification.cs
index 2d6f1436..ca563cc5 100644
--- a/Core/Notification/SoundNotification.cs
+++ b/Core/Notification/SoundNotification.cs
@@ -1,32 +1,53 @@
-using System;
-using TweetLib.Audio;
+using System.Drawing;
+using System.IO;
+using System.Windows.Forms;
+using CefSharp;
+using TweetDuck.Core.Controls;
+using TweetDuck.Core.Other;
+using TweetDuck.Core.Other.Settings;
 
 namespace TweetDuck.Core.Notification{
-    sealed class SoundNotification : IDisposable{
-        public string SupportedFormats => player.SupportedFormats;
-        public event EventHandler<PlaybackErrorEventArgs> PlaybackError;
+    static class SoundNotification{
+        public const string SupportedFormats = "*.wav;*.ogg;*.flac;*.opus;*.weba;*.webm"; // TODO add mp3 when supported
+        
+        public static IResourceHandler CreateFileHandler(string path){
+            string mimeType;
 
-        private readonly AudioPlayer player;
+            switch(Path.GetExtension(path)){
+                case ".weba":
+                case ".webm": mimeType = "audio/webm"; break;
+                case ".wav": mimeType = "audio/wav"; break;
+                case ".ogg": mimeType = "audio/ogg"; break;
+                case ".flac": mimeType = "audio/flac"; break;
+                case ".opus": mimeType = "audio/ogg; codecs=opus"; break;
+                case ".mp3": TryShowError("MP3 sound notifications are temporarily unsupported, please convert the file to another format, such as .ogg, .wav, or .flac."); return null;
+                default: mimeType = null; break;
+            }
 
-        public SoundNotification(){
-            this.player = AudioPlayer.New();
-            this.player.PlaybackError += Player_PlaybackError;
+            try{
+                return ResourceHandler.FromFilePath(path, mimeType);
+            }catch{
+                TryShowError("Could not find custom notification sound file:\n"+path);
+                return null;
+            }
         }
 
-        public void Play(string file){
-            player.Play(file);
-        }
+        private static void TryShowError(string message){
+            FormBrowser browser = FormManager.TryFind<FormBrowser>();
 
-        public bool SetVolume(int volume){
-            return player.SetVolume(volume);
-        }
+            browser?.InvokeAsyncSafe(() => {
+                using(FormMessage form = new FormMessage("Sound Notification Error", message, MessageBoxIcon.Error)){
+                    form.AddButton(FormMessage.Ignore, ControlType.Cancel | ControlType.Focused);
+                        
+                    Button btnViewOptions = form.AddButton("View Options");
+                    btnViewOptions.Width += 16;
+                    btnViewOptions.Location = new Point(btnViewOptions.Location.X-16, btnViewOptions.Location.Y);
 
-        private void Player_PlaybackError(object sender, PlaybackErrorEventArgs e){
-            PlaybackError?.Invoke(this, e);
-        }
-
-        public void Dispose(){
-            player.Dispose();
+                    if (form.ShowDialog() == DialogResult.OK && form.ClickedButton == btnViewOptions){
+                        browser.OpenSettings(typeof(TabSettingsSounds));
+                    }
+                }
+            });
         }
     }
 }
diff --git a/Core/Other/FormSettings.cs b/Core/Other/FormSettings.cs
index 60ae3b9a..38fd460d 100644
--- a/Core/Other/FormSettings.cs
+++ b/Core/Other/FormSettings.cs
@@ -40,7 +40,7 @@ public FormSettings(FormBrowser browser, PluginManager plugins, UpdateHandler up
             AddButton("Locales", () => new TabSettingsLocales());
             AddButton("System Tray", () => new TabSettingsTray());
             AddButton("Notifications", () => new TabSettingsNotifications(new FormNotificationExample(this.browser, this.plugins)));
-            AddButton("Sounds", () => new TabSettingsSounds());
+            AddButton("Sounds", () => new TabSettingsSounds(this.browser.PlaySoundNotification));
             AddButton("Feedback", () => new TabSettingsFeedback(analytics, AnalyticsReportGenerator.ExternalInfo.From(this.browser), this.plugins));
             AddButton("Advanced", () => new TabSettingsAdvanced(this.browser.ReinjectCustomCSS));
 
diff --git a/Core/Other/Settings/TabSettingsSounds.Designer.cs b/Core/Other/Settings/TabSettingsSounds.Designer.cs
index d3784de1..b5bf2596 100644
--- a/Core/Other/Settings/TabSettingsSounds.Designer.cs
+++ b/Core/Other/Settings/TabSettingsSounds.Designer.cs
@@ -36,6 +36,7 @@ private void InitializeComponent() {
             this.trackBarVolume = new System.Windows.Forms.TrackBar();
             this.flowPanel = new System.Windows.Forms.FlowLayoutPanel();
             this.panelVolume = new System.Windows.Forms.Panel();
+            this.volumeUpdateTimer = new System.Windows.Forms.Timer(this.components);
             this.panelSoundNotification.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.trackBarVolume)).BeginInit();
             this.flowPanel.SuspendLayout();
@@ -170,6 +171,11 @@ private void InitializeComponent() {
             this.panelVolume.Size = new System.Drawing.Size(322, 36);
             this.panelVolume.TabIndex = 2;
             // 
+            // volumeUpdateTimer
+            // 
+            this.volumeUpdateTimer.Interval = 250;
+            this.volumeUpdateTimer.Tick += new System.EventHandler(this.volumeUpdateTimer_Tick);
+            // 
             // TabSettingsSounds
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -201,5 +207,6 @@ private void InitializeComponent() {
         private System.Windows.Forms.TrackBar trackBarVolume;
         private System.Windows.Forms.FlowLayoutPanel flowPanel;
         private System.Windows.Forms.Panel panelVolume;
+        private System.Windows.Forms.Timer volumeUpdateTimer;
     }
 }
diff --git a/Core/Other/Settings/TabSettingsSounds.cs b/Core/Other/Settings/TabSettingsSounds.cs
index 8cb3c45b..759fd8ba 100644
--- a/Core/Other/Settings/TabSettingsSounds.cs
+++ b/Core/Other/Settings/TabSettingsSounds.cs
@@ -4,25 +4,18 @@
 using System.Windows.Forms;
 using TweetDuck.Core.Controls;
 using TweetDuck.Core.Notification;
-using TweetLib.Audio;
 
 namespace TweetDuck.Core.Other.Settings{
     sealed partial class TabSettingsSounds : BaseTabSettings{
-        private readonly SoundNotification soundNotification;
-        private readonly bool supportsChangingVolume;
+        private readonly Action playSoundNotification;
 
-        public TabSettingsSounds(){
+        public TabSettingsSounds(Action playSoundNotification){
             InitializeComponent();
 
-            soundNotification = new SoundNotification();
-            soundNotification.PlaybackError += sound_PlaybackError;
-            Disposed += (sender, args) => soundNotification.Dispose();
+            this.playSoundNotification = playSoundNotification;
             
-            supportsChangingVolume = soundNotification.SetVolume(Config.NotificationSoundVolume);
-
             toolTip.SetToolTip(tbCustomSound, "When empty, the default TweetDeck sound notification is used.");
-
-            trackBarVolume.Enabled = supportsChangingVolume && !string.IsNullOrEmpty(Config.NotificationSoundPath);
+            
             trackBarVolume.SetValueSafe(Config.NotificationSoundVolume);
             labelVolumeValue.Text = trackBarVolume.Value+"%";
 
@@ -39,22 +32,29 @@ public override void OnReady(){
 
         public override void OnClosing(){
             Config.NotificationSoundPath = tbCustomSound.Text;
+            Config.NotificationSoundVolume = trackBarVolume.Value;
+        }
+
+        private bool RefreshCanPlay(){
+            bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
+            bool canPlay = isEmpty || File.Exists(tbCustomSound.Text);
+
+            tbCustomSound.ForeColor = canPlay ? SystemColors.WindowText : Color.Red;
+            btnPlaySound.Enabled = canPlay;
+            btnResetSound.Enabled = !isEmpty;
+            return canPlay;
         }
 
         private void tbCustomSound_TextChanged(object sender, EventArgs e){
-            bool isEmpty = string.IsNullOrEmpty(tbCustomSound.Text);
-            tbCustomSound.ForeColor = isEmpty || File.Exists(tbCustomSound.Text) ? SystemColors.WindowText : Color.Red;
-            btnPlaySound.Enabled = !isEmpty;
-            btnResetSound.Enabled = !isEmpty;
-            trackBarVolume.Enabled = supportsChangingVolume && !isEmpty;
+            RefreshCanPlay();
         }
 
         private void btnPlaySound_Click(object sender, EventArgs e){
-            soundNotification.Play(tbCustomSound.Text);
-        }
-
-        private void sound_PlaybackError(object sender, PlaybackErrorEventArgs e){
-            FormMessage.Error("Notification Sound Error", "Could not play custom notification sound.\n"+e.Message, FormMessage.OK);
+            if (RefreshCanPlay()){
+                Config.NotificationSoundPath = tbCustomSound.Text;
+                Config.NotificationSoundVolume = trackBarVolume.Value;
+                playSoundNotification();
+            }
         }
 
         private void btnBrowseSound_Click(object sender, EventArgs e){
@@ -62,7 +62,7 @@ private void btnBrowseSound_Click(object sender, EventArgs e){
                 AutoUpgradeEnabled = true,
                 DereferenceLinks = true,
                 Title = "Custom Notification Sound",
-                Filter = "Sound file ("+soundNotification.SupportedFormats+")|"+soundNotification.SupportedFormats+"|All files (*.*)|*.*"
+                Filter = $"Sound file ({SoundNotification.SupportedFormats})|{SoundNotification.SupportedFormats}|All files (*.*)|*.*"
             }){
                 if (dialog.ShowDialog() == DialogResult.OK){
                     tbCustomSound.Text = dialog.FileName;
@@ -75,9 +75,14 @@ private void btnResetSound_Click(object sender, EventArgs e){
         }
 
         private void trackBarVolume_ValueChanged(object sender, EventArgs e){
+            volumeUpdateTimer.Stop();
+            volumeUpdateTimer.Start();
+            labelVolumeValue.Text = trackBarVolume.Value+"%";
+        }
+
+        private void volumeUpdateTimer_Tick(object sender, EventArgs e){
             Config.NotificationSoundVolume = trackBarVolume.Value;
-            soundNotification.SetVolume(Config.NotificationSoundVolume);
-            labelVolumeValue.Text = Config.NotificationSoundVolume+"%";
+            volumeUpdateTimer.Stop();
         }
     }
 }
diff --git a/Core/TweetDeckBrowser.cs b/Core/TweetDeckBrowser.cs
index 0b0623a4..47fb7ab6 100644
--- a/Core/TweetDeckBrowser.cs
+++ b/Core/TweetDeckBrowser.cs
@@ -7,6 +7,7 @@
 using TweetDuck.Core.Controls;
 using TweetDuck.Core.Handling;
 using TweetDuck.Core.Handling.General;
+using TweetDuck.Core.Notification;
 using TweetDuck.Core.Utils;
 using TweetDuck.Plugins;
 using TweetDuck.Plugins.Enums;
@@ -36,6 +37,8 @@ public bool IsTweetDeckWebsite{
         private readonly ChromiumWebBrowser browser;
         private readonly PluginManager plugins;
 
+        private string prevSoundNotificationPath = null;
+
         public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridge bridge){
             this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
                 DialogHandler = new FileDialogHandler(),
@@ -70,6 +73,7 @@ public TweetDeckBrowser(FormBrowser owner, PluginManager plugins, TweetDeckBridg
             
             Program.UserConfig.MuteToggled += UserConfig_MuteToggled;
             Program.UserConfig.ZoomLevelChanged += UserConfig_ZoomLevelChanged;
+            Program.UserConfig.SoundNotificationChanged += UserConfig_SoundNotificationInfoChanged;
         }
 
         // setup and management
@@ -91,6 +95,7 @@ public void Dispose(){
 
             Program.UserConfig.MuteToggled -= UserConfig_MuteToggled;
             Program.UserConfig.ZoomLevelChanged -= UserConfig_ZoomLevelChanged;
+            Program.UserConfig.SoundNotificationChanged -= UserConfig_SoundNotificationInfoChanged;
             
             browser.Dispose();
         }
@@ -129,6 +134,7 @@ private void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e){
                 ScriptLoader.ExecuteFile(e.Frame, "code.js");
                 InjectBrowserCSS();
                 ReinjectCustomCSS(Program.UserConfig.CustomBrowserCSS);
+                UserConfig_SoundNotificationInfoChanged(null, EventArgs.Empty);
                 plugins.ExecutePlugins(e.Frame, PluginEnvironment.Browser);
 
                 TweetDeckBridge.ResetStaticProperties();
@@ -167,6 +173,27 @@ private void UserConfig_ZoomLevelChanged(object sender, EventArgs e){
             BrowserUtils.SetZoomLevel(browser.GetBrowser(), Program.UserConfig.ZoomLevel);
         }
 
+        private void UserConfig_SoundNotificationInfoChanged(object sender, EventArgs e){
+            const string soundUrl = "https://ton.twimg.com/tduck/updatesnd";
+            bool hasCustomSound = Program.UserConfig.IsCustomSoundNotificationSet;
+
+            if (prevSoundNotificationPath != Program.UserConfig.NotificationSoundPath){
+                DefaultResourceHandlerFactory handlerFactory = browser.GetHandlerFactory();
+                IResourceHandler resourceHandler = hasCustomSound ? SoundNotification.CreateFileHandler(Program.UserConfig.NotificationSoundPath) : null;
+            
+                if (resourceHandler != null){
+                    handlerFactory.RegisterHandler(soundUrl, resourceHandler);
+                }
+                else{
+                    handlerFactory.UnregisterHandler(soundUrl);
+                }
+
+                prevSoundNotificationPath = Program.UserConfig.NotificationSoundPath;
+            }
+
+            browser.ExecuteScriptAsync("TDGF_setSoundNotificationData", hasCustomSound, Program.UserConfig.NotificationSoundVolume);
+        }
+
         // external handling
 
         public UpdateHandler CreateUpdateHandler(UpdaterSettings settings){
@@ -215,6 +242,10 @@ public void ReloadColumns(){
             browser.ExecuteScriptAsync("TDGF_reloadColumns()");
         }
 
+        public void PlaySoundNotification(){
+            browser.ExecuteScriptAsync("TDGF_playSoundNotification()");
+        }
+
         public void ApplyROT13(){
             browser.ExecuteScriptAsync("TDGF_applyROT13()");
         }
diff --git a/Core/Utils/BrowserUtils.cs b/Core/Utils/BrowserUtils.cs
index 7109ce36..90789a68 100644
--- a/Core/Utils/BrowserUtils.cs
+++ b/Core/Utils/BrowserUtils.cs
@@ -35,6 +35,10 @@ public static ChromiumWebBrowser AsControl(this IWebBrowser browserControl){
             return (ChromiumWebBrowser)browserControl;
         }
 
+        public static DefaultResourceHandlerFactory GetHandlerFactory(this ChromiumWebBrowser browser){
+            return (DefaultResourceHandlerFactory)browser.ResourceHandlerFactory;
+        }
+
         private const string TwitterTrackingUrl = "t.co";
 
         public enum UrlCheckResult{
diff --git a/Resources/Scripts/code.js b/Resources/Scripts/code.js
index d3526bbf..1d66c8c4 100644
--- a/Resources/Scripts/code.js
+++ b/Resources/Scripts/code.js
@@ -507,10 +507,35 @@
   //
   // Block: Hook into the notification sound effect.
   //
+  
   HTMLAudioElement.prototype.play = prependToFunction(HTMLAudioElement.prototype.play, function(){
-    return $TDX.muteNotifications || $TDX.hasCustomNotificationSound;
+    return $TDX.muteNotifications;
   });
   
+  window.TDGF_setSoundNotificationData = function(custom, volume){
+    let audio = document.getElementById("update-sound");
+    audio.volume = volume/100;
+    
+    const sourceId = "tduck-custom-sound-source";
+    let source = document.getElementById(sourceId);
+    
+    if (custom && !source){
+      source = document.createElement("source");
+      source.id = sourceId;
+      source.src = "https://ton.twimg.com/tduck/updatesnd";
+      audio.prepend(source);
+    }
+    else if (!custom && source){
+      audio.removeChild(source);
+    }
+    
+    audio.load();
+  };
+  
+  window.TDGF_playSoundNotification = function(){
+    document.getElementById("update-sound").play();
+  };
+  
   //
   // Block: Update highlighted column and tweet for context menu and other functionality.
   //
diff --git a/TweetDuck.csproj b/TweetDuck.csproj
index 23423925..038ed7f3 100644
--- a/TweetDuck.csproj
+++ b/TweetDuck.csproj
@@ -378,10 +378,6 @@
     <Content Include="Resources\Scripts\update.js" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="lib\TweetLib.Audio\TweetLib.Audio.csproj">
-      <Project>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</Project>
-      <Name>TweetLib.Audio</Name>
-    </ProjectReference>
     <ProjectReference Include="subprocess\TweetDuck.Browser.csproj">
       <Project>{b10b0017-819e-4f71-870f-8256b36a26aa}</Project>
       <Name>TweetDuck.Browser</Name>
diff --git a/TweetDuck.sln b/TweetDuck.sln
index 95c0b692..f4155fbc 100644
--- a/TweetDuck.sln
+++ b/TweetDuck.sln
@@ -8,8 +8,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Browser", "subpro
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "tests\UnitTests.csproj", "{A958FA7A-4A2C-42A7-BFA0-159343483F4E}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Audio", "lib\TweetLib.Audio\TweetLib.Audio.csproj", "{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetDuck.Video", "video\TweetDuck.Video.csproj", "{278B2D11-402D-44B6-B6A1-8FA67DB65565}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TweetLib.Communication", "lib\TweetLib.Communication\TweetLib.Communication.csproj", "{72473763-4B9D-4FB6-A923-9364B2680F06}"
@@ -32,10 +30,6 @@ Global
 		{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.ActiveCfg = Debug|x86
 		{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Debug|x86.Build.0 = Debug|x86
 		{A958FA7A-4A2C-42A7-BFA0-159343483F4E}.Release|x86.ActiveCfg = Release|x86
-		{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.ActiveCfg = Debug|x86
-		{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Debug|x86.Build.0 = Debug|x86
-		{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.ActiveCfg = Release|x86
-		{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}.Release|x86.Build.0 = Release|x86
 		{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.ActiveCfg = Debug|x86
 		{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Debug|x86.Build.0 = Debug|x86
 		{278B2D11-402D-44B6-B6A1-8FA67DB65565}.Release|x86.ActiveCfg = Release|x86
diff --git a/bld/gen_upd.iss b/bld/gen_upd.iss
index fa3b0d18..eba60747 100644
--- a/bld/gen_upd.iss
+++ b/bld/gen_upd.iss
@@ -59,6 +59,7 @@ Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\Cache"
 Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\GPUCache"
 
 [InstallDelete]
+Type: files; Name: "{app}\TweetLib.Audio.dll"
 Type: filesandordirs; Name: "{app}\plugins\official"
 Type: files; Name: "{app}\locales\am.pak"
 Type: files; Name: "{app}\locales\ar.pak"
diff --git a/lib/TweetLib.Audio/AudioPlayer.cs b/lib/TweetLib.Audio/AudioPlayer.cs
deleted file mode 100644
index 29879ec8..00000000
--- a/lib/TweetLib.Audio/AudioPlayer.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using TweetLib.Audio.Impl;
-
-namespace TweetLib.Audio{
-    public abstract class AudioPlayer : IDisposable{
-        private static bool? IsWMPAvailable;
-
-        public static AudioPlayer New(){
-            if (IsWMPAvailable.HasValue){
-                if (IsWMPAvailable.Value){
-                    return new SoundPlayerImplWMP();
-                }
-                else{
-                    return new SoundPlayerImplFallback();
-                }
-            }
-
-            try{
-                SoundPlayerImplWMP implWMP = new SoundPlayerImplWMP();
-                IsWMPAvailable = true;
-                return implWMP;
-            }catch(COMException){
-                IsWMPAvailable = false;
-                return new SoundPlayerImplFallback();
-            }
-        }
-
-        public abstract string SupportedFormats { get; }
-        public abstract event EventHandler<PlaybackErrorEventArgs> PlaybackError;
-
-        public abstract void Play(string file);
-        public abstract bool SetVolume(int volume);
-        protected abstract void Dispose(bool disposing);
-
-        public void Dispose(){
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-    }
-}
diff --git a/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs b/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs
deleted file mode 100644
index e13021ce..00000000
--- a/lib/TweetLib.Audio/Impl/SoundPlayerImplFallback.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using System.IO;
-using System.Media;
-
-namespace TweetLib.Audio.Impl{
-    sealed class SoundPlayerImplFallback : AudioPlayer{
-        public override string SupportedFormats => "*.wav";
-
-        public override event EventHandler<PlaybackErrorEventArgs> PlaybackError;
-
-        private readonly SoundPlayer player;
-        private bool ignorePlaybackError;
-
-        public SoundPlayerImplFallback(){
-            player = new SoundPlayer{
-                LoadTimeout = 5000
-            };
-        }
-
-        public override void Play(string file){
-            if (player.SoundLocation != file){
-                player.SoundLocation = file;
-                ignorePlaybackError = false;
-            }
-
-            try{
-                player.Play();
-            }catch(FileNotFoundException e){
-                OnNotificationSoundError("File not found: "+e.FileName);
-            }catch(InvalidOperationException){
-                OnNotificationSoundError("File format was not recognized.");
-            }catch(TimeoutException){
-                OnNotificationSoundError("File took too long to load.");
-            }
-        }
-
-        public override bool SetVolume(int volume){
-            return false;
-        }
-
-        protected override void Dispose(bool disposing){
-            player.Dispose();
-        }
-
-        private void OnNotificationSoundError(string message){
-            if (!ignorePlaybackError){
-                PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
-                PlaybackError?.Invoke(this, args);
-                ignorePlaybackError = args.Ignore;
-            }
-        }
-    }
-}
diff --git a/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs b/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs
deleted file mode 100644
index b68376aa..00000000
--- a/lib/TweetLib.Audio/Impl/SoundPlayerImplWMP.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using System.Windows.Forms;
-using WMPLib;
-
-namespace TweetLib.Audio.Impl{
-    sealed class SoundPlayerImplWMP : AudioPlayer{
-        public override string SupportedFormats => "*.wav;*.mp3;*.mp2;*.m4a;*.mid;*.midi;*.rmi;*.wma;*.aif;*.aifc;*.aiff;*.snd;*.au";
-
-        public override event EventHandler<PlaybackErrorEventArgs> PlaybackError;
-
-        private readonly Form owner;
-        private readonly ControlWMP wmp;
-        private bool wasTryingToPlay;
-        private bool ignorePlaybackError;
-
-        private WindowsMediaPlayer Player => wmp.Ocx;
-        
-        public SoundPlayerImplWMP(){
-            owner = new Form();
-            wmp = new ControlWMP();
-            wmp.BeginInit();
-            owner.Controls.Add(wmp);
-            wmp.EndInit();
-            
-            Player.uiMode = "none";
-            Player.settings.autoStart = false;
-            Player.settings.enableErrorDialogs = false;
-            Player.settings.invokeURLs = false;
-            Player.settings.volume = 0;
-            Player.MediaChange += player_MediaChange;
-            Player.MediaError += player_MediaError;
-        }
-
-        public override void Play(string file){
-            wasTryingToPlay = true;
-
-            try{
-                if (Player.URL != file){
-                    Player.close();
-                    Player.URL = file;
-                    ignorePlaybackError = false;
-                }
-                else{
-                    Player.controls.stop();
-                }
-            
-                Player.controls.play();
-            }catch(Exception e){
-                OnNotificationSoundError("An error occurred in Windows Media Player: "+e.Message);
-            }
-        }
-
-        public override bool SetVolume(int volume){
-            Player.settings.volume = volume;
-            return true;
-        }
-
-        protected override void Dispose(bool disposing){
-            wmp.Dispose();
-            owner.Dispose();
-        }
-
-        private void player_MediaChange(object item){
-            IWMPMedia2 media = item as IWMPMedia2;
-
-            if (media == null){
-                OnNotificationSoundError("Unknown error.");
-                return;
-            }
-            // ReSharper disable once CompareOfFloatsByEqualityOperator
-            else if (media.Error == null && media.duration == 0.0){
-                OnNotificationSoundError("File does not contain an audio track.");
-            }
-            else if (media.Error != null){
-                OnNotificationSoundError(media.Error);
-            }
-
-            Marshal.ReleaseComObject(media);
-        }
-
-        private void player_MediaError(object pMediaObject){
-            IWMPMedia2 media = pMediaObject as IWMPMedia2;
-
-            if (media == null){
-                OnNotificationSoundError("Unknown error.");
-                return;
-            }
-            else if (media.Error != null){
-                OnNotificationSoundError(media.Error);
-            }
-
-            Marshal.ReleaseComObject(media);
-        }
-
-        private void OnNotificationSoundError(IWMPErrorItem error){
-            OnNotificationSoundError(error.errorCode == -1072885353 ? "Invalid media file." : error.errorDescription);
-            Marshal.ReleaseComObject(error);
-        }
-
-        private void OnNotificationSoundError(string message){
-            if (wasTryingToPlay){
-                wasTryingToPlay = false;
-
-                if (!ignorePlaybackError){
-                    PlaybackErrorEventArgs args = new PlaybackErrorEventArgs(message);
-                    PlaybackError?.Invoke(this, args);
-                    ignorePlaybackError = args.Ignore;
-                }
-            }
-        }
-
-        [Clsid("{6bf52a52-394a-11d3-b153-00c04f79faa6}")]
-        private sealed class ControlWMP : AxHost{
-            public WindowsMediaPlayer Ocx { get; private set; }
-
-            public ControlWMP() : base("6bf52a52-394a-11d3-b153-00c04f79faa6"){}
-
-            protected override void AttachInterfaces(){
-                Ocx = (WindowsMediaPlayer)GetOcx();
-            }
-        }
-    }
-}
diff --git a/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs b/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs
deleted file mode 100644
index f8f07325..00000000
--- a/lib/TweetLib.Audio/PlaybackErrorEventArgs.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-
-namespace TweetLib.Audio{
-    public sealed class PlaybackErrorEventArgs : EventArgs{
-        public string Message { get; }
-        public bool Ignore { get; set; }
-
-        public PlaybackErrorEventArgs(string message){
-            this.Message = message;
-            this.Ignore = false;
-        }
-    }
-}
diff --git a/lib/TweetLib.Audio/Properties/AssemblyInfo.cs b/lib/TweetLib.Audio/Properties/AssemblyInfo.cs
deleted file mode 100644
index c38326d2..00000000
--- a/lib/TweetLib.Audio/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("TweetDuck Audio Library")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("TweetDuck Audio Library")]
-[assembly: AssemblyCopyright("")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components.  If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("e9e1fd1b-f480-45b7-9970-be2ecfd309ac")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.1.1.0")]
-[assembly: AssemblyFileVersion("1.1.1.0")]
diff --git a/lib/TweetLib.Audio/TweetLib.Audio.csproj b/lib/TweetLib.Audio/TweetLib.Audio.csproj
deleted file mode 100644
index 69adb783..00000000
--- a/lib/TweetLib.Audio/TweetLib.Audio.csproj
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
-    <ProjectGuid>{E9E1FD1B-F480-45B7-9970-BE2ECFD309AC}</ProjectGuid>
-    <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>TweetLib.Audio</RootNamespace>
-    <AssemblyName>TweetLib.Audio</AssemblyName>
-    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <ResolveComReferenceSilent>True</ResolveComReferenceSilent>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
-    <PlatformTarget>x86</PlatformTarget>
-    <OutputPath>bin\x86\Debug\</OutputPath>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
-    <PlatformTarget>x86</PlatformTarget>
-    <OutputPath>bin\x86\Release\</OutputPath>
-    <Optimize>true</Optimize>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Windows.Forms" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="AudioPlayer.cs" />
-    <Compile Include="PlaybackErrorEventArgs.cs" />
-    <Compile Include="Impl\SoundPlayerImplFallback.cs" />
-    <Compile Include="Impl\SoundPlayerImplWMP.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <COMReference Include="WMPLib">
-      <Guid>{6BF52A50-394A-11D3-B153-00C04F79FAA6}</Guid>
-      <VersionMajor>1</VersionMajor>
-      <VersionMinor>0</VersionMinor>
-      <Lcid>0</Lcid>
-      <WrapperTool>tlbimp</WrapperTool>
-      <Isolated>False</Isolated>
-      <EmbedInteropTypes>True</EmbedInteropTypes>
-    </COMReference>
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-</Project>
\ No newline at end of file