forked from tokland/youtube-upload
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
32 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,5 @@ | ||
#!/usr/bin/python2 | ||
# | ||
# Youtube-upload is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# Youtube-upload is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with Youtube-upload. If not, see <http://www.gnu.org/licenses/>. | ||
# | ||
# Author: Arnau Sanchez <[email protected]> | ||
# Site: https://github.com/tokland/youtube-upload | ||
""" | ||
|
@@ -21,7 +8,7 @@ | |
$ youtube-upload --title="A.S. Mutter playing" \ | ||
--description="Anne Sophie Mutter plays Beethoven" \ | ||
--category=Music \ | ||
--keywords="mutter, beethoven" \ | ||
--tags="mutter, beethoven" \ | ||
anne_sophie_mutter.flv | ||
www.youtube.com/watch?v=pxzZ-fYjeYs | ||
""" | ||
|
@@ -43,31 +30,17 @@ | |
progressbar = None | ||
|
||
class InvalidCategory(Exception): pass | ||
class VideoArgumentMissing(Exception): pass | ||
class OptionsMissing(Exception): pass | ||
class BadAuthentication(Exception): pass | ||
class ParseError(Exception): pass | ||
class VideoNotFound(Exception): pass | ||
class UnsuccessfulHTTPResponseCode(Exception): pass | ||
|
||
VERSION = "0.8.0" | ||
|
||
EXIT_CODES = { | ||
# Non-retryable | ||
BadAuthentication: 1, | ||
VideoArgumentMissing: 2, | ||
OptionsMissing: 2, | ||
InvalidCategory: 3, | ||
ParseError: 5, | ||
VideoNotFound: 6, | ||
# Retryable | ||
UnsuccessfulHTTPResponseCode: 100, | ||
} | ||
|
||
WATCH_VIDEO_URL = "https://www.youtube.com/watch?v={id}" | ||
|
||
ProgressInfo = collections.namedtuple("ProgressInfo", ["callback", "finish"]) | ||
|
||
def to_utf8(s): | ||
"""Re-encode string from the default system encoding to UTF-8.""" | ||
current = locale.getpreferredencoding() | ||
|
@@ -114,21 +87,34 @@ def _callback(total_size, completed): | |
bar.maxval = total_size | ||
bar.start() | ||
bar.update(completed) | ||
|
||
widgets = [ | ||
progressbar.Percentage(), ' ', | ||
progressbar.Bar(), ' ', | ||
progressbar.ETA(), ' ', | ||
progressbar.FileTransferSpeed(), | ||
] | ||
bar = progressbar.ProgressBar(widgets=widgets) | ||
return ProgressInfo(callback=_callback, finish=bar.finish) | ||
build = collections.namedtuple("ProgressInfo", ["callback", "finish"]) | ||
|
||
if progressbar: | ||
widgets = [ | ||
progressbar.Percentage(), ' ', | ||
progressbar.Bar(), ' ', | ||
progressbar.ETA(), ' ', | ||
progressbar.FileTransferSpeed(), | ||
] | ||
bar = progressbar.ProgressBar(widgets=widgets) | ||
return build(callback=_callback, finish=bar.finish) | ||
else: | ||
return build(callback=lambda *args: True, finish=lambda: True) | ||
|
||
def string_to_dict(string): | ||
"""Return dictionary from string "key1=value1, key2=value2".""" | ||
pairs = [s.strip() for s in (string or "").split(",")] | ||
return dict(pair.split("=") for pair in pairs) | ||
|
||
def get_category_id(category): | ||
"""Return category ID from its name.""" | ||
if category: | ||
if category in youtube_upload.categories.IDS: | ||
return str(youtube_upload.categories.IDS[category]) | ||
else: | ||
msg = "{} is not a valid category".format(category) | ||
raise InvalidCategory(msg) | ||
|
||
def upload_video(youtube, options, video_path, total_videos, index): | ||
"""Upload video with index (for split videos).""" | ||
title = to_utf8(options.title) | ||
|
@@ -137,20 +123,12 @@ def upload_video(youtube, options, video_path, total_videos, index): | |
complete_title = \ | ||
(options.title_template.format(**ns) if total_videos > 1 else title) | ||
progress = get_progress_info() | ||
if options.category: | ||
ids = youtube_upload.categories.IDS | ||
if options.category in ids: | ||
category_id = str(ids[options.category]) | ||
else: | ||
msg = "{} is not a valid category".format(options.category) | ||
raise InvalidCategory(msg) | ||
else: | ||
category_id = None | ||
category_id = get_category_id(options.category) | ||
|
||
body = { | ||
"snippet": { | ||
"title": complete_title, | ||
"tags": map(str.strip, (options.keywords or "").split(",")), | ||
"tags": map(str.strip, (options.tags or "").split(",")), | ||
"description": description, | ||
"categoryId": category_id, | ||
}, | ||
|
@@ -180,7 +158,7 @@ def run_main(parser, options, args, output=sys.stdout): | |
default_client_secrets = \ | ||
os.path.join(sys.prefix, "share/youtube_upload/client_secrets.json") | ||
home = os.path.expanduser("~") | ||
default_credentials = os.path.join(home, ".youtube_upload-credentials.json") | ||
default_credentials = os.path.join(home, ".youtube-upload-credentials.json") | ||
client_secrets = options.client_secrets or default_client_secrets | ||
credentials = options.credentials_file or default_credentials | ||
debug("Using client secrets: {}".format(client_secrets)) | ||
|
@@ -190,11 +168,11 @@ def run_main(parser, options, args, output=sys.stdout): | |
for index, video_path in enumerate(args): | ||
video_id = upload_video(youtube, options, video_path, len(args), index) | ||
video_url = WATCH_VIDEO_URL.format(id=video_id) | ||
debug("Watch URL: {}".format(video_url)) | ||
debug("Video URL: {}".format(video_url)) | ||
output.write(video_id + "\n") | ||
|
||
def main(arguments): | ||
"""Upload video to Youtube.""" | ||
"""Upload videos to Youtube.""" | ||
usage = """Usage: %prog [OPTIONS] VIDEO_PATH [VIDEO_PATH2 ...] | ||
Upload videos to youtube.""" | ||
|
@@ -209,8 +187,8 @@ def main(arguments): | |
# Optional options | ||
parser.add_option('-d', '--description', dest='description', type="string", | ||
help='Video(s) description') | ||
parser.add_option('', '--keywords', dest='keywords', type="string", | ||
help='Video(s) keywords (separated by commas: tag1,tag2,...)') | ||
parser.add_option('', '--tags', dest='tags', type="string", | ||
help='Video(s) tags (separated by commas: tag1,tag2,...)') | ||
parser.add_option('', '--title-template', dest='title_template', | ||
type="string", default="{title} [{n}/{total}]", metavar="STRING", | ||
help='Template for multiple videos (default: {title} [{n}/{total}])') | ||
|