Repository: streamlink/streamlink
Pull request #491 (2017-01-26 11:14:14)

Localization/HLS fixes
Some fixes for some issues that have come up with wider testing of the Localization and HLS external audio streams. 


Patch:
diff --git a/src/streamlink/stream/hls.py b/src/streamlink/stream/hls.py
index f52c7958..9e260537 100644
--- a/src/streamlink/stream/hls.py
+++ b/src/streamlink/stream/hls.py
@@ -370,7 +370,7 @@ class HLSStream(HTTPStream):
                     continue
 
             external_audio = preferred_audio or default_audio
-            if external_audio and external_audio.uri:
+            if external_audio and external_audio.uri and FFMPEGMuxer.is_usable(session_):
                 logger.debug("Using external audio track for stream {0} (language={1})".format(
                     name_prefix + stream_name,
                     external_audio.language))
diff --git a/src/streamlink/utils/l10n.py b/src/streamlink/utils/l10n.py
index 44972b4c..80083609 100644
--- a/src/streamlink/utils/l10n.py
+++ b/src/streamlink/utils/l10n.py
@@ -6,9 +6,6 @@ DEFAULT_LANGUAGE_CODE = "en_US"
 
 
 class Localization(object):
-    language_code_remap = {
-        "fre": "fra"
-    }
 
     def __init__(self, language_code=None):
         self._language_code = None
@@ -40,8 +37,12 @@ class Localization(object):
 
     def equivalent(self, language=None, country=None):
         equivalent = True
-        equivalent = equivalent and (not language or self.language == self.get_language(language))
-        equivalent = equivalent and (not country or self.country == self.get_country(country))
+        try:
+            equivalent = equivalent and (not language or self.language == self.get_language(language))
+            equivalent = equivalent and (not country or self.country == self.get_country(country))
+        except KeyError:
+            # if an unknown language/country code is given they cannot equivalent
+            return False
 
         return equivalent
 
@@ -54,13 +55,16 @@ class Localization(object):
 
     @classmethod
     def get_language(cls, language):
-        # some language codes need to be remapped. why? because standards were designed to be broken.
-        _language = cls.language_code_remap.get(language, language)
         try:
-            if len(_language) == 2:
-                return languages.get(alpha2=_language)
-            elif len(_language) == 3:
-                return languages.get(part3=_language)
+            if len(language) == 2:
+                return languages.get(alpha2=language)
+            elif len(language) == 3:
+                for code_type in ['part2b', 'part2t', 'part3']:
+                    try:
+                        return languages.get(**{code_type: language})
+                    except KeyError:
+                        pass
+                raise KeyError
             else:
                 raise ValueError("Invalid language code: {0}".format(language))
         except KeyError:


Test patch:
diff --git a/tests/test_localization.py b/tests/test_localization.py
index dbdc7f90..42cea044 100644
--- a/tests/test_localization.py
+++ b/tests/test_localization.py
@@ -58,12 +58,13 @@ class TestLocalization(unittest.TestCase):
 
     def test_get_language(self):
         self.assertEqual("eng",
-                         Localization.get_language("en").part3)
-        self.assertEqual("fra",
-                         Localization.get_language("fra").part3)
-        self.assertEqual("fra",
-                         Localization.get_language("fre").part3,
-                         msg="fre should be remapped to fra")
+                         Localization.get_language("en").part2b)
+        self.assertEqual("fre",
+                         Localization.get_language("fra").part2b)
+        self.assertEqual("fre",
+                         Localization.get_language("fre").part2b)
+        self.assertEqual("gre",
+                         Localization.get_language("gre").part2b)
 
     def test_get_language_miss(self):
         self.assertRaises(ValueError, Localization.get_language, "00")