1
#!/usr/bin/env python
2
# -*- coding: utf8 -*-
3
u"""
4
5
Arte-DL
6
-------
7
8
Downloads a video from the french-german TV channel ARTE.
9
10
Dependencies:
11
12
- ``rtmpdump`` to download the video stream.
13
14
.. :Authors:
15
       Aurélien Bompard <aurelien@bompard.org> <http://aurelien.bompard.org>
16
17
.. :License:
18
       GNU GPL v3 or later
19
"""
20
21
import sys
22
import os
23
import re
24
import urllib2
25
from xml.etree import ElementTree as etree
26
import subprocess
27
from optparse import OptionParser
28
29
MAX_TRIES = 10
30
31
def get_video_id(url):
32
    match = re.match("http://videos\.arte\.tv/(\w\w)/videos/([^/]+-\d+)\.html", url)
33
    if not match:
34
        print >>sys.stderr, "Can't find the video ID in the URL"
35
        if options.debug:
36
            print url
37
        sys.exit(1)
38
    return match.group(1), match.group(2)
39
40
def get_video_info(lang, basename):
41
    url = "http://videos.arte.tv/%s/do_delegate/videos/%s,view,asPlayerXml.xml" % (lang, basename)
42
    videoref = etree.parse(urllib2.urlopen(url))
43
    video_info_tag = [ t for t in videoref.findall("videos/video")
44
                               if t.get("lang") == lang ]
45
    if not video_info_tag:
46
        print >>sys.stderr, "Can't find the video info URL in the videoref info XML"
47
        if options.debug:
48
            etree.dump(videoref)
49
        sys.exit(1)
50
    video_info_url = video_info_tag[0].get("ref")
51
    video_info = etree.parse(urllib2.urlopen(video_info_url))
52
    return video_info
53
54
def get_video_url(video_info, quality):
55
    url_tag = [ t for t in video_info.findall("urls/url") if t.get("quality") == quality.lower() ]
56
    if not url_tag:
57
        print >>sys.stderr, "Can't find the video URL in the video info XML"
58
        if options.debug:
59
            etree.dump(video_info)
60
        sys.exit(1)
61
    return url_tag[0].text.strip()
62
63
def get_video_name(video_info):
64
    return video_info.findtext("name").strip()
65
66
def download_video(url, filename):
67
    command = ["rtmpdump", "-r", url, "-o", filename]
68
    if os.path.exists(filename):
69
        command.insert(1, "--resume")
70
    for arg in command:
71
        if arg.count(" ") or arg.count("&"):
72
            print '"%s"' % arg,
73
        else:
74
            print arg,
75
    print
76
    if options.debug:
77
        return
78
    retcode = subprocess.call(command)
79
    return retcode
80
81
def main():
82
    global options
83
    usage = "%prog [options] URL"
84
    parser = OptionParser(usage)
85
    parser.add_option("-q", "--quality", dest="quality",
86
                      default="HD", metavar="SD/HD",
87
                      help="quality (SD or HD, defaults to %default)")
88
    parser.add_option("-o", "--output", dest="output", metavar="FILENAME",
89
                      help="filename for the downloaded video")
90
    parser.add_option("-d", "--debug", action="store_true",
91
                      dest="debug", default=False,
92
                      help="only display which command would be run")
93
    options, args = parser.parse_args()
94
    if not len(args) > 0:
95
        parser.error("Missing URL")
96
    url = args[0]
97
    lang, basename = get_video_id(url)
98
    video_info = get_video_info(lang, basename)
99
    video_url = get_video_url(video_info, options.quality)
100
    video_name = get_video_name(video_info)
101
    if options.debug:
102
        print "URL: ", video_url
103
    if options.output:
104
        filename = options.output
105
        if not filename.endswith(".flv"):
106
            filename += ".flv"
107
    else:
108
        filename = "Arte - %s.flv" % video_name
109
        print u"Downloading video %s in file %s." \
110
                % (video_name, filename)
111
        print "Choose a new filename, or leave empty to accept the default filename."
112
        newfilename = raw_input("--> ")
113
        if newfilename:
114
            filename = newfilename
115
    retcode = download_video(video_url, filename)
116
    # rtmpdump returns 2 if the download is incomplete
117
    current_try = 1
118
    while retcode == 2:
119
        print "Trying again..."
120
        retcode = download_video(video_url, filename)
121
        current_try += 1
122
        if current_try > MAX_TRIES:
123
            print "Too many tries, aborting."
124
            break
125
126
127
if __name__ == "__main__":
128
    main()