Repository: ytdl-org/youtube-dl

Issue:
ValueError when downloading a video from YouTube
Downloading [this video](https://www.youtube.com/watch?v=Ms7iBXnlUO8) seems to fail:

```
$ PYTHONPATH=`pwd`  ./bin/youtube-dl --verbose --list-formats 'https://www.youtube.com/watch?v=Ms7iBXnlUO8'
[debug] System config: []
[debug] User config: []
[debug] Command-line args: [u'--verbose', u'--list-formats', u'https://www.youtube.com/watch?v=Ms7iBXnlUO8']
[debug] Encodings: locale UTF-8, fs UTF-8, out UTF-8, pref UTF-8
[debug] youtube-dl version 2015.11.10
[debug] Git HEAD: fcd817a
[debug] Python version 2.7.9 - Linux-3.19.0-33-generic-x86_64-with-Ubuntu-15.04-vivid
[debug] exe versions: ffmpeg 2.5.8-0ubuntu0.15.04.1, ffprobe 2.5.8-0ubuntu0.15.04.1, rtmpdump 2.4
[debug] Proxy map: {}
[youtube] Ms7iBXnlUO8: Downloading webpage
Traceback (most recent call last):
  File "./bin/youtube-dl", line 6, in <module>
    youtube_dl.main()
  File "/home/lukas/work/youtube-dl/youtube_dl/__init__.py", line 410, in main
    _real_main(argv)
  File "/home/lukas/work/youtube-dl/youtube_dl/__init__.py", line 400, in _real_main
    retcode = ydl.download(all_urls)
  File "/home/lukas/work/youtube-dl/youtube_dl/YoutubeDL.py", line 1666, in download
    url, force_generic_extractor=self.params.get('force_generic_extractor', False))
  File "/home/lukas/work/youtube-dl/youtube_dl/YoutubeDL.py", line 661, in extract_info
    ie_result = ie.extract(url)
  File "/home/lukas/work/youtube-dl/youtube_dl/extractor/common.py", line 290, in extract
    return self._real_extract(url)
  File "/home/lukas/work/youtube-dl/youtube_dl/extractor/youtube.py", line 1080, in _real_extract
    ytplayer_config = json.loads(json_code)
  File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Unterminated string starting at: line 1 column 6498 (char 6497)
```



Discussion:
The problem is that the video has keywords set to `"info: {}});}, n);}};(function(w, startTick"` (really) and the current regex cuts it in the middle. One possible fix would be to change the regex:

``` diff
diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py
index 687e0b4..2173118 100644
--- a/youtube_dl/extractor/youtube.py
+++ b/youtube_dl/extractor/youtube.py
@@ -1074,7 +1074,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
             age_gate = False
             video_info = None
             # Try looking directly into the video webpage
-            mobj = re.search(r';ytplayer\.config\s*=\s*({.*?});', video_webpage)
+            mobj = re.search(r';ytplayer\.config\s*=\s*({.*?});ytplayer', video_webpage)
             if mobj:
                 json_code = uppercase_escape(mobj.group(1))
                 ytplayer_config = json.loads(json_code)
```

Another video affected by this  - https://www.youtube.com/watch?v=lsguqyKfVQg


Resolving patch:
diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py
--- a/youtube_dl/extractor/youtube.py
+++ b/youtube_dl/extractor/youtube.py
@@ -674,7 +674,23 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
         {
             'url': 'http://vid.plus/FlRa-iH7PGw',
             'only_matching': True,
-        }
+        },
+        {
+            # Title with JS-like syntax "};"
+            'url': 'https://www.youtube.com/watch?v=lsguqyKfVQg',
+            'info_dict': {
+                'id': 'lsguqyKfVQg',
+                'ext': 'mp4',
+                'title': '{dark walk}; Loki/AC/Dishonored; collab w/Elflover21',
+                'description': 'md5:8085699c11dc3f597ce0410b0dcbb34a',
+                'upload_date': '20151119',
+                'uploader_id': 'IronSoulElf',
+                'uploader': 'IronSoulElf',
+            },
+            'params': {
+                'skip_download': True,
+            },
+        },
     ]
 
     def __init__(self, *args, **kwargs):
@@ -858,16 +874,24 @@ def _get_subtitles(self, video_id, webpage):
             return {}
         return sub_lang_list
 
+    def _get_ytplayer_config(self, webpage):
+        patterns = [
+            r';ytplayer\.config\s*=\s*({.*?});ytplayer',
+            r';ytplayer\.config\s*=\s*({.*?});',
+        ]
+        config = self._search_regex(patterns, webpage, 'ytconfig.player', default=None)
+        if config is not None:
+            return json.loads(uppercase_escape(config))
+
     def _get_automatic_captions(self, video_id, webpage):
         """We need the webpage for getting the captions url, pass it as an
            argument to speed up the process."""
         self.to_screen('%s: Looking for automatic captions' % video_id)
-        mobj = re.search(r';ytplayer.config = ({.*?});', webpage)
+        player_config = self._get_ytplayer_config(webpage)
         err_msg = 'Couldn\'t find automatic captions for %s' % video_id
-        if mobj is None:
+        if player_config is None:
             self._downloader.report_warning(err_msg)
             return {}
-        player_config = json.loads(mobj.group(1))
         try:
             args = player_config['args']
             caption_url = args['ttsurl']
@@ -1074,10 +1098,8 @@ def add_dash_mpd(video_info):
             age_gate = False
             video_info = None
             # Try looking directly into the video webpage
-            mobj = re.search(r';ytplayer\.config\s*=\s*({.*?});', video_webpage)
-            if mobj:
-                json_code = uppercase_escape(mobj.group(1))
-                ytplayer_config = json.loads(json_code)
+            ytplayer_config = self._get_ytplayer_config(video_webpage)
+            if ytplayer_config is not None:
                 args = ytplayer_config['args']
                 if args.get('url_encoded_fmt_stream_map'):
                     # Convert to the same format returned by compat_parse_qs


Test patch: