Repository: ytdl-org/youtube-dl

Issue:
Google Drive Support Request (Similar to YouTube?)
Hi,

Please would you add support for Google Drive video previews. It looks like it may operate similar to YouTube.

$ youtube-dl --verbose 'https://docs.google.com/file/d/0Bwi6Ha03myF1aGVweVBoemdlU3c/preview?pli=1'
[debug] System config: []
[debug] User config: []
[debug] Command-line args: ['--verbose', 'https://docs.google.com/file/d/0Bwi6Ha03myF1aGVweVBoemdlU3c/preview?pli=1']
[debug] Encodings: locale 'UTF-8', fs 'utf-8', out 'UTF-8', pref: 'UTF-8'
[debug] youtube-dl version 2014.01.22
[debug] Python version 3.3.3 - Linux-3.12.8-1-ARCH-x86_64-with-arch
[debug] Proxy map: {}
[generic] preview?pli=1: Requesting header
WARNING: Falling back on generic information extractor.
[generic] preview?pli=1: Downloading webpage
[generic] preview?pli=1: Extracting information
ERROR: Unsupported URL: https://docs.google.com/file/d/0Bwi6Ha03myF1aGVweVBoemdlU3c/preview?pli=1; please report this issue on https://yt-dl.org/bug . Be sure to call youtube-dl with the --verbose flag and include its complete output. Make sure you are using the latest version; type  youtube-dl -U  to update.
Traceback (most recent call last):
  File "/usr/lib/python3.3/site-packages/youtube_dl/YoutubeDL.py", line 494, in extract_info
    ie_result = ie.extract(url)
  File "/usr/lib/python3.3/site-packages/youtube_dl/extractor/common.py", line 156, in extract
    return self._real_extract(url)
  File "/usr/lib/python3.3/site-packages/youtube_dl/extractor/generic.py", line 353, in _real_extract
    raise ExtractorError('Unsupported URL: %s' % url)
youtube_dl.utils.ExtractorError: Unsupported URL: https://docs.google.com/file/d/0Bwi6Ha03myF1aGVweVBoemdlU3c/preview?pli=1; please report this issue on https://yt-dl.org/bug . Be sure to call youtube-dl with the --verbose flag and include its complete output. Make sure you are using the latest version; type  youtube-dl -U  to update.



Discussion:
I second that. Wish Google Drive support.

example URL https://drive.google.com/folderview?id=0B9g_WLKRYa99M3VFQlJrN0dXa3M&usp=sharing

I would also greatly benefit this. youtube-dl supports dropbox, and it's my favorite way of actually being able to download dropbox things.

Users often decide to send me test files or other things related to my development via Google Drive, and it's always a big hassle to guide them through the process of re-uploading it to somewhere that actually works.

It would be really neat if youtube-dl could support Google Drive links natively so this would no longer be a problem.

That said, I think this may be slightly out of scope of youtube-dl, at least in terms of its typical intent as being used for video sharing platforms. Maybe youtube-dl could be generalized, or maybe this would be better off as a separate project?


Resolving patch:
diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py
--- a/youtube_dl/extractor/__init__.py
+++ b/youtube_dl/extractor/__init__.py
@@ -209,6 +209,7 @@
 from .godtube import GodTubeIE
 from .goldenmoustache import GoldenMoustacheIE
 from .golem import GolemIE
+from .googledrive import GoogleDriveIE
 from .googleplus import GooglePlusIE
 from .googlesearch import GoogleSearchIE
 from .gorillavid import GorillaVidIE
diff --git a/youtube_dl/extractor/generic.py b/youtube_dl/extractor/generic.py
--- a/youtube_dl/extractor/generic.py
+++ b/youtube_dl/extractor/generic.py
@@ -48,6 +48,7 @@
 from .dailymotion import DailymotionCloudIE
 from .onionstudios import OnionStudiosIE
 from .snagfilms import SnagFilmsEmbedIE
+from .googledrive import GoogleDriveIE
 
 
 class GenericIE(InfoExtractor):
@@ -1599,6 +1600,11 @@ def _playlist_from_matches(matches, getter=None, ie=None):
         if nbc_sports_url:
             return self.url_result(nbc_sports_url, 'NBCSportsVPlayer')
 
+        # Look for Google Drive embeds
+        google_drive_url = GoogleDriveIE._extract_url(webpage)
+        if google_drive_url:
+            return self.url_result(google_drive_url, 'GoogleDrive')
+
         # Look for UDN embeds
         mobj = re.search(
             r'<iframe[^>]+src="(?P<url>%s)"' % UDNEmbedIE._VALID_URL, webpage)
diff --git a/youtube_dl/extractor/googledrive.py b/youtube_dl/extractor/googledrive.py
new file mode 100644
--- /dev/null
+++ b/youtube_dl/extractor/googledrive.py
@@ -0,0 +1,88 @@
+from __future__ import unicode_literals
+
+import re
+
+from .common import InfoExtractor
+from ..utils import (
+    ExtractorError,
+    int_or_none,
+)
+
+
+class GoogleDriveIE(InfoExtractor):
+    _VALID_URL = r'https?://(?:(?:docs|drive)\.google\.com/(?:uc\?.*?id=|file/d/)|video\.google\.com/get_player\?.*?docid=)(?P<id>[a-zA-Z0-9_-]{28})'
+    _TEST = {
+        'url': 'https://drive.google.com/file/d/0ByeS4oOUV-49Zzh4R1J6R09zazQ/edit?pli=1',
+        'md5': '881f7700aec4f538571fa1e0eed4a7b6',
+        'info_dict': {
+            'id': '0ByeS4oOUV-49Zzh4R1J6R09zazQ',
+            'ext': 'mp4',
+            'title': 'Big Buck Bunny.mp4',
+            'duration': 46,
+        }
+    }
+    _FORMATS_EXT = {
+        '5': 'flv',
+        '6': 'flv',
+        '13': '3gp',
+        '17': '3gp',
+        '18': 'mp4',
+        '22': 'mp4',
+        '34': 'flv',
+        '35': 'flv',
+        '36': '3gp',
+        '37': 'mp4',
+        '38': 'mp4',
+        '43': 'webm',
+        '44': 'webm',
+        '45': 'webm',
+        '46': 'webm',
+        '59': 'mp4',
+    }
+
+    @staticmethod
+    def _extract_url(webpage):
+        mobj = re.search(
+            r'<iframe[^>]+src="https?://(?:video\.google\.com/get_player\?.*?docid=|(?:docs|drive)\.google\.com/file/d/)(?P<id>[a-zA-Z0-9_-]{28})',
+            webpage)
+        if mobj:
+            return 'https://drive.google.com/file/d/%s' % mobj.group('id')
+
+    def _real_extract(self, url):
+        video_id = self._match_id(url)
+        webpage = self._download_webpage(
+            'http://docs.google.com/file/d/%s' % video_id, video_id, encoding='unicode_escape')
+
+        reason = self._search_regex(r'"reason"\s*,\s*"([^"]+)', webpage, 'reason', default=None)
+        if reason:
+            raise ExtractorError(reason)
+
+        title = self._search_regex(r'"title"\s*,\s*"([^"]+)', webpage, 'title')
+        duration = int_or_none(self._search_regex(
+            r'"length_seconds"\s*,\s*"([^"]+)', webpage, 'length seconds', default=None))
+        fmt_stream_map = self._search_regex(
+            r'"fmt_stream_map"\s*,\s*"([^"]+)', webpage, 'fmt stream map').split(',')
+        fmt_list = self._search_regex(r'"fmt_list"\s*,\s*"([^"]+)', webpage, 'fmt_list').split(',')
+
+        formats = []
+        for fmt, fmt_stream in zip(fmt_list, fmt_stream_map):
+            fmt_id, fmt_url = fmt_stream.split('|')
+            resolution = fmt.split('/')[1]
+            width, height = resolution.split('x')
+            formats.append({
+                'url': fmt_url,
+                'format_id': fmt_id,
+                'resolution': resolution,
+                'width': int_or_none(width),
+                'height': int_or_none(height),
+                'ext': self._FORMATS_EXT[fmt_id],
+            })
+        self._sort_formats(formats)
+
+        return {
+            'id': video_id,
+            'title': title,
+            'thumbnail': self._og_search_thumbnail(webpage),
+            'duration': duration,
+            'formats': formats,
+        }


Test patch: