diff --git a/sickbeard/common.py b/sickbeard/common.py
index 9f68d6fb7595dab3207c6e2a353b16978fcc4000..a0532c632a60c4bdab20f6d445fca460b4a82059 100644
--- a/sickbeard/common.py
+++ b/sickbeard/common.py
@@ -24,7 +24,6 @@ Common interface for Quality and Status
 
 # pylint: disable=line-too-long
 
-
 import operator
 from os import path
 import platform
@@ -38,6 +37,10 @@ from hachoir_core.log import log  # pylint: disable=import-error
 from fake_useragent import settings as UA_SETTINGS, UserAgent
 from sickbeard.numdict import NumDict
 from sickrage.helper.encoding import ek
+from sickrage.helper.common import try_int
+from sickrage.tagger.episode import EpisodeTags
+from sickrage.recompiled import tags
+
 
 # If some provider has an issue with functionality of SR, other than user agents, it's best to come talk to us rather than block.
 # It is no different than us going to a provider if we have questions or issues. Be a team player here.
@@ -124,6 +127,12 @@ class Quality(object):
     FULLHDWEBDL = 1 << 6  # 64 -- 1080p web-dl
     HDBLURAY = 1 << 7  # 128
     FULLHDBLURAY = 1 << 8  # 256
+    UHD_4K_TV = 1 << 9  # 512 -- 2160p aka 4K UHD aka UHD-1
+    UHD_4K_WEBDL = 1 << 10  # 1024
+    UHD_4K_BLURAY = 1 << 11  # 2048
+    UHD_8K_TV = 1 << 12  # 4096 -- 4320p aka 8K UHD aka UHD-2
+    UHD_8K_WEBDL = 1 << 13  # 8192
+    UHD_8K_BLURAY = 1 << 14  # 16384
     ANYHDTV = HDTV | FULLHDTV  # 20
     ANYWEBDL = HDWEBDL | FULLHDWEBDL  # 96
     ANYBLURAY = HDBLURAY | FULLHDBLURAY  # 384
@@ -143,7 +152,13 @@ class Quality(object):
         HDWEBDL: "720p WEB-DL",
         FULLHDWEBDL: "1080p WEB-DL",
         HDBLURAY: "720p BluRay",
-        FULLHDBLURAY: "1080p BluRay"
+        FULLHDBLURAY: "1080p BluRay",
+        UHD_4K_TV: "4K UHD TV",
+        UHD_8K_TV: "8K UHD TV",
+        UHD_4K_WEBDL: "4K UHD WEB-DL",
+        UHD_8K_WEBDL: "8K UHD WEB-DL",
+        UHD_4K_BLURAY: "4K UHD BluRay",
+        UHD_8K_BLURAY: "8K UHD BluRay",
     })
 
     sceneQualityStrings = NumDict({
@@ -158,7 +173,13 @@ class Quality(object):
         HDWEBDL: "720p WEB-DL",
         FULLHDWEBDL: "1080p WEB-DL",
         HDBLURAY: "720p BluRay",
-        FULLHDBLURAY: "1080p BluRay"
+        FULLHDBLURAY: "1080p BluRay",
+        UHD_4K_TV: "4K UHD TV",
+        UHD_8K_TV: "8K UHD TV",
+        UHD_4K_WEBDL: "4K UHD WEB-DL",
+        UHD_8K_WEBDL: "8K UHD WEB-DL",
+        UHD_4K_BLURAY: "4K UHD BluRay",
+        UHD_8K_BLURAY: "8K UHD BluRay",
     })
 
     combinedQualityStrings = NumDict({
@@ -180,6 +201,12 @@ class Quality(object):
         FULLHDWEBDL: "HD1080p",
         HDBLURAY: "HD720p",
         FULLHDBLURAY: "HD1080p",
+        UHD_4K_TV: "UHD-4K",
+        UHD_8K_TV: "UHD-8K",
+        UHD_4K_WEBDL: "UHD-4K",
+        UHD_8K_WEBDL: "UHD-8K",
+        UHD_4K_BLURAY: "UHD-4K",
+        UHD_8K_BLURAY: "UHD-8K",
         ANYHDTV: "any-hd",
         ANYWEBDL: "any-hd",
         ANYBLURAY: "any-hd"
@@ -212,13 +239,13 @@ class Quality(object):
         return to_return
 
     @staticmethod
-    def combineQualities(any_qualities, best_qualities):
+    def combineQualities(allowed_qualities, prefferred_qualities):
         any_quality = 0
         best_quality = 0
-        if any_qualities:
-            any_quality = reduce(operator.or_, any_qualities)
-        if best_qualities:
-            best_quality = reduce(operator.or_, best_qualities)
+        if allowed_qualities:
+            any_quality = reduce(operator.or_, allowed_qualities)
+        if prefferred_qualities:
+            best_quality = reduce(operator.or_, prefferred_qualities)
         return any_quality | (best_quality << 16)
 
     @staticmethod
@@ -260,7 +287,7 @@ class Quality(object):
         return Quality.UNKNOWN
 
     @staticmethod
-    def sceneQuality(name, anime=False):  # pylint: disable=too-many-branches
+    def old_scene_quality(name, anime=False):  # pylint: disable=too-many-branches
         """
         Return The quality from the scene episode File
 
@@ -322,6 +349,107 @@ class Quality(object):
 
         return ret
 
+    @staticmethod
+    def scene_quality(name, anime=False):  # pylint: disable=too-many-branches
+        """
+        Return The quality from the scene episode File
+
+        :param name: Episode filename to analyse
+        :param anime: Boolean to indicate if the show we're resolving is Anime
+        :return: Quality prefix
+        """
+
+        if not name:
+            return Quality.UNKNOWN
+        else:
+            name = ek(path.basename, name)
+
+        result = None
+        ep = EpisodeTags(name)
+
+        if anime:
+            sd_options = tags.anime_sd.search(name)
+            hd_options = tags.anime_hd.search(name)
+            full_hd = tags.anime_fullhd.search(name)
+
+            # BluRay
+            if ep.bluray and (full_hd or hd_options):
+                result = Quality.FULLHDBLURAY if full_hd else Quality.HDBLURAY
+            # HD TV
+            elif not ep.bluray and (full_hd or hd_options):
+                result = Quality.FULLHDTV if full_hd else Quality.HDTV
+            # SD DVD
+            elif ep.dvd:
+                result = Quality.SDDVD
+            # SD TV
+            elif sd_options:
+                result = Quality.SDTV
+
+            return Quality.UNKNOWN if result is None else result
+
+        # Is it UHD?
+        if ep.vres in [2160, 4320] and ep.scan == u'p':
+            # BluRay
+            full_res = (ep.vres == 4320)
+            if ep.avc and ep.bluray:
+                result = Quality.UHD_4K_BLURAY if not full_res else Quality.UHD_8K_BLURAY
+            # WEB-DL
+            elif (ep.avc and ep.itunes) or ep.web:
+                result = Quality.UHD_4K_WEBDL if not full_res else Quality.UHD_8K_WEBDL
+            # HDTV
+            elif ep.avc and ep.tv == u'hd':
+                result = Quality.UHD_4K_TV if not full_res else Quality.UHD_8K_TV
+
+        # Is it HD?
+        elif ep.vres in [1080, 720]:
+            if ep.scan == u'p':
+                # BluRay
+                full_res = (ep.vres == 1080)
+                if ep.avc and (ep.bluray or ep.hddvd):
+                    result = Quality.FULLHDBLURAY if full_res else Quality.HDBLURAY
+                # WEB-DL
+                elif (ep.avc and ep.itunes) or ep.web:
+                    result = Quality.FULLHDWEBDL if full_res else Quality.HDWEBDL
+                # HDTV
+                elif ep.avc and ep.tv == u'hd':
+                    if not all([ep.vres == 1080, ep.raw, ep.avc_non_free]):
+                        result = Quality.FULLHDTV if full_res else Quality.HDTV
+                    else:
+                        result = Quality.RAWHDTV
+                elif all([ep.vres == 720, ep.tv == u'hd', ep.mpeg]):
+                    result = Quality.RAWHDTV
+            elif (ep.res == u'1080i') and ep.tv == u'hd':
+                if ep.mpeg or (ep.raw and ep.avc_non_free):
+                    result = Quality.RAWHDTV
+        elif ep.hrws:
+            result = Quality.HDTV
+
+        # Is it SD?
+        elif ep.xvid or ep.avc:
+            # SD DVD
+            if ep.dvd or ep.bluray:
+                result = Quality.SDDVD
+            # SDTV
+            elif ep.res == u'480p' or any([ep.tv, ep.sat, ep.web]):
+                result = Quality.SDTV
+
+        new = result or Quality.UNKNOWN
+        if new <= Quality.FULLHDBLURAY or new == Quality.UNKNOWN:
+            old = Quality.old_scene_quality(name, anime)
+            assert old == new, 'Old quality does not match new: %s != %s : %s' % (Quality.qualityStrings[old], Quality.qualityStrings[new], name)
+
+        return Quality.UNKNOWN if result is None else result
+
+    @staticmethod
+    def sceneQuality(name, anime=False):
+        # new = Quality.scene_quality(name, anime)
+        #
+        # if new <= Quality.FULLHDBLURAY or new == Quality.UNKNOWN:
+        #     old = Quality.old_scene_quality(name, anime)
+        #     assert old == new, 'New quality does not match old: %s != %s : %s' % (Quality.qualityStrings[new], Quality.qualityStrings[old], name)
+
+        return Quality.scene_quality(name, anime)
+
     @staticmethod
     def assumeQuality(name):
         """
@@ -389,11 +517,15 @@ class Quality(object):
         webdl = re.search(r"web.?dl|web(rip|mux|hd)", base_filename, re.I) is not None
 
         ret = Quality.UNKNOWN
-        if height > 1000:
+        if 3240 < height:
+            ret = ((Quality.UHD_8K_TV, Quality.UHD_8K_BLURAY)[bluray], Quality.UHD_8K_WEBDL)[webdl]
+        if 1620 < height <= 3240:
+            ret = ((Quality.UHD_4K_TV, Quality.UHD_4K_BLURAY)[bluray], Quality.UHD_4K_WEBDL)[webdl]
+        elif 800 < height <= 1620:
             ret = ((Quality.FULLHDTV, Quality.FULLHDBLURAY)[bluray], Quality.FULLHDWEBDL)[webdl]
-        elif 680 < height < 800:
+        elif 680 < height <= 800:
             ret = ((Quality.HDTV, Quality.HDBLURAY)[bluray], Quality.HDWEBDL)[webdl]
-        elif height < 680:
+        elif height <= 680:
             ret = (Quality.SDTV, Quality.SDDVD)[re.search(r'dvd|b[rd]rip|blue?-?ray', base_filename, re.I) is not None]
 
         return ret
@@ -516,21 +648,32 @@ Quality.ARCHIVED = [Quality.compositeStatus(ARCHIVED, x) for x in Quality.qualit
 
 HD720p = Quality.combineQualities([Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], [])
 HD1080p = Quality.combineQualities([Quality.FULLHDTV, Quality.FULLHDWEBDL, Quality.FULLHDBLURAY], [])
+UHD_4K = Quality.combineQualities([Quality.UHD_4K_TV, Quality.UHD_4K_WEBDL, Quality.UHD_4K_BLURAY], [])
+UHD_8K = Quality.combineQualities([Quality.UHD_8K_TV, Quality.UHD_8K_WEBDL, Quality.UHD_8K_BLURAY], [])
 
 SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], [])
 HD = Quality.combineQualities([HD720p, HD1080p], [])
-ANY = Quality.combineQualities([SD, HD], [])
+UHD = Quality.combineQualities([UHD_4K, UHD_8K], [])
+ANY = Quality.combineQualities([SD, HD, UHD], [])
 
 # legacy template, cant remove due to reference in mainDB upgrade?
 BEST = Quality.combineQualities([Quality.SDTV, Quality.HDTV, Quality.HDWEBDL], [Quality.HDTV])
 
-qualityPresets = (SD, HD, HD720p, HD1080p, ANY)
+qualityPresets = (
+    SD,
+    HD, HD720p, HD1080p,
+    UHD, UHD_4K, UHD_8K,
+    ANY,
+)
 qualityPresetStrings = NumDict({
     SD: "SD",
     HD: "HD",
     HD720p: "HD720p",
     HD1080p: "HD1080p",
-    ANY: "Any"
+    UHD: "UHD",
+    UHD_4K: "UHD-4K",
+    UHD_8K: "UHD-8K",
+    ANY: "Any",
 })
 
 
diff --git a/sickrage/recompiled/__init__.py b/sickrage/recompiled/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/sickrage/recompiled/tags.py b/sickrage/recompiled/tags.py
new file mode 100644
index 0000000000000000000000000000000000000000..398481577b69072c83d20498068a7bb3c2ddf785
--- /dev/null
+++ b/sickrage/recompiled/tags.py
@@ -0,0 +1,24 @@
+
+import re
+
+
+# Resolutions
+resolution = re.compile(r'(?P<vres>4320|2160|1080|720|480|360)(?P<scan>[pi])', re.IGNORECASE)
+
+# Sources
+tv = re.compile(r'([sph]d).?tv|tv(rip|mux)', re.IGNORECASE)
+dvd = re.compile(r'(?P<hd>hd)dvd|dvd(?P<rip>rip|mux)', re.IGNORECASE)
+web = re.compile(r'(web.?(?P<dl>dl)|web(?P<rip>rip|mux|hd))', re.IGNORECASE)
+bluray = re.compile(r'(blue?-?ray|b[rd](?:rip|mux))', re.IGNORECASE)
+sat = re.compile(r'(dsr|satrip)', re.IGNORECASE)
+itunes = re.compile(r'(itunes)', re.IGNORECASE)
+
+# Codecs
+avc = re.compile(r'([xh].?26[45])', re.IGNORECASE)
+xvid = re.compile(r'(xvid|divx)', re.IGNORECASE)
+mpeg = re.compile(r'(mpeg-?2)', re.IGNORECASE)
+
+# anime
+anime_sd = re.compile(r'(848x480|480p|360p|xvid)', re.IGNORECASE)
+anime_hd = re.compile(r'((1280|960)x720|720p)', re.IGNORECASE)
+anime_fullhd = re.compile(r'(1920x1080|1080p)', re.IGNORECASE)
diff --git a/sickrage/tagger/__init__.py b/sickrage/tagger/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/sickrage/tagger/episode.py b/sickrage/tagger/episode.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3c9543400b0ca970ff5752ec5935f980061f5a5
--- /dev/null
+++ b/sickrage/tagger/episode.py
@@ -0,0 +1,246 @@
+# coding=utf-8
+
+"""
+Episode tagger to extract information from episodes
+"""
+
+from __future__ import unicode_literals
+
+import re
+from sickrage.recompiled import tags
+from sickrage.helper.common import try_int
+
+
+class EpisodeTags(object):
+    """
+    Quality tags
+    """
+    def __init__(self, name):
+        self.name = name
+        self.rex = {
+            u'res': tags.resolution,
+            u'bluray': tags.bluray,
+            u'web': tags.web,
+            u'itunes': tags.itunes,
+            u'dvd': tags.dvd,
+            u'sat': tags.sat,
+            u'tv': tags.tv,
+            u'avc': tags.avc,
+            u'mpeg': tags.mpeg,
+            u'xvid': tags.xvid,
+        }
+
+    def _get_match_obj(self, attr, regex=None, flags=0):
+        match_obj = '%s_match' % attr
+        try:
+            return getattr(self, match_obj)
+        except (KeyError, AttributeError):
+            regex = regex or self.rex[attr]
+            result = regex.search(self.name, flags)
+            setattr(self, match_obj, result)
+            return result
+
+    # RESOLUTION
+    @property
+    def res(self):
+        """
+        The resolution tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'res'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group().lower()
+
+    @property
+    def vres(self):
+        """
+        The vertical found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'res'
+        match = self._get_match_obj(attr)
+        return None if not match else try_int(match.group('vres'))
+
+    @property
+    def scan(self):
+        """
+        The type of scan found in the name
+
+        e.g. `i` for Interlaced, `p` for Progressive Scan
+
+        :returns: an empty string if not found
+        """
+        attr = 'res'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group('scan').lower()
+
+    # SOURCES
+    @property
+    def bluray(self):
+        """
+        The bluray tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'bluray'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group()
+
+    @property
+    def hddvd(self):
+        """
+        The hddvd tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'dvd'
+        match = self._get_match_obj(attr)
+        return None if not match else match.group('hd')
+
+    @property
+    def itunes(self):
+        """
+        The iTunes tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'itunes'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group()
+
+    @property
+    def web(self):
+        """
+        The web tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'web'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group('dl') or match.group('rip')
+
+    @property
+    def sat(self):
+        """
+        The sat tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'sat'
+        match = self._get_match_obj(attr)
+        return None if not match else match.group()
+
+    @property
+    def dvd(self):
+        """
+        The dvd tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'dvd'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group('rip')
+
+    @property
+    def tv(self):
+        attr = 'tv'
+        match = self._get_match_obj(attr)
+        return '' if not match else (match.group(1) or match.group(2)).lower()
+
+    # CODECS
+    @property
+    def hevc(self):
+        """
+        The hevc tag found in the name
+
+        :returns: an empty string if not found
+        """
+        return '' if not (self.avc[:-1] == '5') else self.avc
+
+    @property
+    def avc(self):
+        """
+        The avc tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'avc'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group()
+
+    @property
+    def avc_free(self):
+        """
+        The free avc codec found in the name
+        e.g.: x.265 or X264
+
+        :returns: an empty string if not found
+        """
+        return u'' if self.avc[0].lower() != 'x' else self.avc
+
+    @property
+    def avc_non_free(self):
+        """
+        The non-free avc codec found in the name
+        e.g.: h.265 or H264
+
+        :returns: an empty string if not found
+        """
+        return u'' if self.avc[0].lower() != 'h' else self.avc
+
+    @property
+    def mpeg(self):
+        """
+        The mpeg tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'mpeg'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group()
+
+    @property
+    def xvid(self):
+        """
+        The xvid tag found in the name
+
+        :returns: an empty string if not found
+        """
+        attr = 'xvid'
+        match = self._get_match_obj(attr)
+        return '' if not match else match.group()
+
+    # MISCELLANEOUS
+    @property
+    def hrws(self):
+        """
+        The hrws tag found in the name
+
+        HR = High Resolution
+        WS = Wide Screen
+        PD TV = Pure Digital Television
+
+        :returns: an empty string if not found
+        """
+        attr = 'hrws'
+        match = None
+        if self.avc and self.tv == 'pd':
+            regex = re.compile(ur'(hr.ws.pdtv).%s' % self.avc, re.IGNORECASE)
+            match = self._get_match_obj(attr, regex)
+        return '' if not match else match.group()
+
+    @property
+    def raw(self):
+        """
+        The raw tag found in the name
+
+        :return: an empty string if not found
+        """
+        attr = 'raw'
+        match = None
+        if self.res and self.tv == 'hd':
+            regex = re.compile(ur'(%s.hdtv)' % self.res, re.IGNORECASE)
+            match = self._get_match_obj(attr, regex)
+        return '' if not match else match.group()
diff --git a/tests/common_tests.py b/tests/common_tests.py
index 9dd29d9d17808fbbc0bd1d6d494c62bf20f67216..e7f654cac5102edad840b0b4d86b76831636c6b7 100644
--- a/tests/common_tests.py
+++ b/tests/common_tests.py
@@ -97,7 +97,9 @@ class QualityStringTests(unittest.TestCase):
                       "Test.Show.S01E02.720p.HDDVD.x264-GROUP", ],
         'full_hd_bluray': ["Test.Show.S01E02.1080p.BluRay.x264-GROUP",
                            "Test.Show.S01E02.1080p.HDDVD.x264-GROUP", ],
-        'unknown': ["Test.Show.S01E02-SiCKBEARD", ],
+        'unknown': ["Test.Show.S01E02-SiCKBEARD",
+                    "Test.Show.S01E01-20.1080i.[Mux.-.1080i.-.H264.-.Ac3.].HDTVMux.GROUP",
+                    ],
     }
 
     def test_sd_tv(self):