Browse Source

add lib module

Arnau Sanchez 10 years ago
parent
commit
c04c9a3fe4
4 changed files with 63 additions and 186 deletions
  1. 0 113
      CHANGELOG
  2. 12 13
      README.md
  3. 38 0
      youtube_upload/lib.py
  4. 13 60
      youtube_upload/main.py

+ 0 - 113
CHANGELOG

@@ -1,113 +0,0 @@
-youtube-upload (0.8.0) stable; urgency=low
-
-  * Update to APIv3 and Oauth2.
-
-youtube-upload (0.7.4) stable; urgency=low
-
-  * issue131: New options --nocomments, --noratings, --recorded
-  * issue136: Issue with split_video_for_youtube.sh
-  * add keywords to option update-metadata
-
- --  <pyarnau@gmail.com>  Mon, 06 May 2013 14:20:04 +0200
-
-youtube-upload (0.7.3) stable; urgency=low
-
-  * issue101: don't fail when no description is provided 
-  * issue107: add options --hide-progressbar
-
- --  <pyarnau@gmail.com>  Mon, 06 May 2013 14:20:04 +0200
-
-youtube-upload (0.7.2) stable; urgency=low
-
-  * Change --email option help message.
-  * Allow escaped chars in description
-  * Add -update-metadata (basic support: title/description)
-
- --  <pyarnau@gmail.com>  Wed, 31 May 2012 18:58:44 +0200
-
-youtube-upload (0.7.1) stable; urgency=low
-
-  * Format checks on video URL and playlists.
-  * Add option --unlisted (issue60).
-  * Fix progressbar on finish.
-
- --  <pyarnau@gmail.com>  Wed, 1 May 2012 18:58:44 +0200
-
-youtube-upload (0.7) stable; urgency=low
-
-  * Prompt password when not specified in command line.
-  * Meaningful error codes. 
-  * Update to progressbar v2.3.
-
- --  <pyarnau@gmail.com>  Thu, 11 Aug 2011 09:54:47 +0200
-
-youtube-upload (0.6.2) unstable; urgency=low
-
-  * Add option to create playlist
-  * Add pycurl + progression bar
-
- --  <pyarnau@gmail.com>  Sat, 23 Apr 2011 20:06:34 +0200
-
-youtube-upload (0.6.1) unstable; urgency=low
-
-  * fix issue with required options
-
- --  <pyarnau@gmail.com>  Fri, 25 Mar 2011 21:01:29 +0100
-
-youtube-upload (0.6) unstable; urgency=low
-
-  * Remove ffmpeg spliting from Python script (orthogonal task)
-  * Move all arguments to options except video paths.
-  * Bash script to split videos: split_video_for_youtube.sh
-
- --  <pyarnau@gmail.com>  Thu, 10 Mar 2011 18:50:45 +0100
-
-youtube-upload (0.5) unstable; urgency=low
-
-  * Update to new Youtube limits (15mins, 2Gb) 
-  * Add curl options to bash script
-  * Fix encoding for debug (issue10)
-  * Fix location bug (issue11)
-  * Fix keywords splitting (issue13)
-  * Add --wait-processed option (issue19)
-
- --  <pyarnau@gmail.com>  Wed, 29 Sep 2010 11:31:18 +0200
-
-youtube-upload (0.4) unstable; urgency=low
-
-  * issue7: fix for gdata 2.0.10
-  * issue9: password can be passed through <stdin>
-  * Add --location option
-  * Add --private option
-  * Add --playlist-uri option
-  * Add Bash example: Upload a video using curl
-
- --  <pyarnau@gmail.com>  Tue, 29 Jun 2010 19:45:40 +0200
-
-youtube-upload (0.3) unstable; urgency=low
-
-  * Keep quality of original video on slipt.
-
- --  <pyarnau@gmail.com>  Sat, 17 Apr 2010 16:01:58 +0200
-
-youtube-upload (0.2) unstable; urgency=low
-
-  * Refactor video split
-  * Create split file only when necessary
-  * Add setup.py
-
- --  <pyarnau@gmail.com>  Tue, 16 Mar 2010 22:56:21 +0100
-
-youtube-upload (0.1) unstable; urgency=high
-
-  * Detect deprecated categories.
-  * Validate meta-data before uploading the video.
-  * Split files in chunks (youtube limits to 10') using ffmpeg.
-
- --  <pyarnau@gmail.com>  Tue, 08 Dec 2009 19:49:02 +0100
-
-youtube-upload (0.0.1) unstable; urgency=high
- 
-  * First release.
-
- -- Arnau Sanchez <pyarnau@gmail.com>  Sat, 24 Jan 2009 12:17:21 +0200

+ 12 - 13
README.md

@@ -1,17 +1,16 @@
 Introduction
 ============
 
-_Youtube-upload_ is a command-line script that uploads videos to Youtube. 
-
-_Youtube-upload_ should work on any platform (GNU/Linux, BSD, OS X, Windows, ...) that runs Python.
+_Youtube-upload_ is a command-line script that uploads videos to Youtube (it should work on any platform -GNU/Linux, BSD, OS X, Windows, ...- that runs Python).
 
 Dependencies
 ============
 
-  * [Python 2.6 or 2.7](http://www.python.org)
+  * [Python 2.6 or 2.7](http://www.python.org). Python 3.0 is NOT supported.
   * [Python Google API](https://github.com/google/google-api-python-client)
 
-Download & Install
+Install
+=======
 
 ```
 $ wget https://github.com/tokland/youtube-upload/archive/master.zip
@@ -27,8 +26,8 @@ $ cd youtube-upload-master
 $ PYTHONPATH=. python youtube_upload/youtube_upload.py ...
 ```
 
-Usage examples
-==============
+Examples
+========
 
 * Upload a video:
 
@@ -49,7 +48,7 @@ pxzZ-fYjeYs
 
 * Split a video with _ffmpeg_
 
-Youtube currently limits videos to <2Gb and <15' for almost all users. You can use the Bash example script to split it before uploading:
+Youtube currently limits videos to <2Gb and <15' for almost all users. You can use the example script to split it before uploading:
 
 ```
 $ bash examples/split_video_for_youtube.sh video.avi
@@ -71,15 +70,15 @@ $ youtube-upload ....
 Caveats
 =======
 
-* The package includes a default file but if you plan to use a heavy usage of the script, please [create and use your own authentication file](https://developers.google.com/youtube/v3/getting-started).
+* The package includes a default ```client_secrets.json``` file, but if you plan to make a heavy use of the script, please [create and use your own authentication file](https://developers.google.com/youtube/v3/getting-started).
 
-* If a video does not comply with Youtube size limitations you must split it before using ffmpeg/avconv or any other tool. 
+* If a video does not comply with Youtube size limitations you must split it (using ffmpeg/avconvm, for example). 
 
 More
 ====
 
-* License: [GNU/GPL v3](http://www.gnu.org/licenses/gpl.html). 
+* License: [GNU/GPLv3](http://www.gnu.org/licenses/gpl.html). 
 
-* [Open a issue](https://github.com/tokland/youtube-upload/issues).
+* Feedback: [Open a issue](https://github.com/tokland/youtube-upload/issues).
 
-* [Support the developer with a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=pyarnau%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHostedGuest).
+* [Donate](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=pyarnau%40gmail%2ecom&lc=US&no_note=0&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHostedGuest).

+ 38 - 0
youtube_upload/lib.py

@@ -0,0 +1,38 @@
+import sys
+import locale
+
+def to_utf8(s):
+    """Re-encode string from the default system encoding to UTF-8."""
+    current = locale.getpreferredencoding()
+    return s.decode(current).encode("UTF-8") if s and current != "UTF-8" else s
+
+def debug(obj, fd=sys.stderr):
+    """Write obj to standard error."""
+    string = str(obj.encode(get_encoding(fd), "backslashreplace")
+                 if isinstance(obj, unicode) else obj)
+    fd.write(string + "\n")
+
+def catch_exceptions(exit_codes, fun, *args, **kwargs):
+    """
+    Catch exceptions on fun(*args, **kwargs) and return the exit code specified
+    in the exit_codes dictionary. Return 0 if no exception is raised.
+    """
+    try:
+        fun(*args, **kwargs)
+        return 0
+    except tuple(exit_codes.keys()) as exc:
+        debug("[%s] %s" % (exc.__class__.__name__, exc))
+        return exit_codes[exc.__class__]
+
+def get_encoding(fd):
+    """Guess terminal encoding."""
+    return fd.encoding or locale.getpreferredencoding()
+
+def first(it):
+    """Return first element in iterable."""
+    return it.next()
+
+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)

+ 13 - 60
youtube_upload/main.py

@@ -1,7 +1,7 @@
 #!/usr/bin/python2
 #
 # Author: Arnau Sanchez <pyarnau@gmail.com>
-# Site: https://github.com/tokland/youtube-upload
+# Project site: https://github.com/tokland/youtube-upload
 """
 Upload a video to Youtube from the command-line.
 
@@ -15,13 +15,13 @@ Upload a video to Youtube from the command-line.
 
 import os
 import sys
-import locale
 import optparse
 import collections
 
 import youtube_upload.auth
 import youtube_upload.upload_video
 import youtube_upload.categories
+import youtube_upload.lib as lib
 
 # http://code.google.com/p/python-progressbar (>= 2.3)
 try:
@@ -32,8 +32,6 @@ except ImportError:
 class InvalidCategory(Exception): pass
 class OptionsMissing(Exception): pass
 
-VERSION = "0.8.0"
-
 EXIT_CODES = {
     OptionsMissing: 2,
     InvalidCategory: 3,
@@ -41,44 +39,7 @@ EXIT_CODES = {
 
 WATCH_VIDEO_URL = "https://www.youtube.com/watch?v={id}"
 
-def to_utf8(s):
-    """Re-encode string from the default system encoding to UTF-8."""
-    current = locale.getpreferredencoding()
-    return s.decode(current).encode("UTF-8") if s and current != "UTF-8" else s
-
-def debug(obj, fd=sys.stderr):
-    """Write obj to standard error."""
-    string = str(obj.encode(get_encoding(fd), "backslashreplace")
-                 if isinstance(obj, unicode) else obj)
-    fd.write(string + "\n")
-
-def catch_exceptions(exit_codes, fun, *args, **kwargs):
-    """
-    Catch exceptions on fun(*args, **kwargs) and return the exit code specified
-    in the exit_codes dictionary. Return 0 if no exception is raised.
-    """
-    try:
-        fun(*args, **kwargs)
-        return 0
-    except tuple(exit_codes.keys()) as exc:
-        debug("[%s] %s" % (exc.__class__.__name__, exc))
-        return exit_codes[exc.__class__]
-
-def get_encoding(fd):
-    """Guess terminal encoding."""
-    return fd.encoding or locale.getpreferredencoding()
-
-def compact(it):
-    """Filter false (in the truth sense) elements in iterator."""
-    return filter(bool, it)
-
-def tosize(seq, size):
-    """Return list of fixed length from sequence."""
-    return seq[:size] if len(seq) >= size else (seq + [None] * (size-len(seq)))
-
-def first(it):
-    """Return first element in iterable."""
-    return it.next()
+debug = lib.debug
 
 def get_progress_info():
     """Return a function callback to update the progressbar."""
@@ -99,12 +60,7 @@ def get_progress_info():
         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)
+        return build(callback=None, finish=lambda: True)
 
 def get_category_id(category):
     """Return category ID from its name."""
@@ -117,14 +73,13 @@ def get_category_id(category):
 
 def upload_video(youtube, options, video_path, total_videos, index):
     """Upload video with index (for split videos)."""
-    title = to_utf8(options.title)
-    description = to_utf8(options.description or "").decode("string-escape")
+    title = lib.to_utf8(options.title)
+    description = lib.to_utf8(options.description or "").decode("string-escape")
     ns = dict(title=title, n=index+1, total=total_videos)
     complete_title = \
         (options.title_template.format(**ns) if total_videos > 1 else title)
     progress = get_progress_info()
     category_id = get_category_id(options.category)
-
     body = {
         "snippet": {
             "title": complete_title,
@@ -136,7 +91,7 @@ def upload_video(youtube, options, video_path, total_videos, index):
             "privacyStatus": options.privacy
         },
         "recordingDetails": {
-            "location": string_to_dict(options.location),
+            "location": lib.string_to_dict(options.location),
         },
     }
 
@@ -176,27 +131,25 @@ def main(arguments):
     usage = """Usage: %prog [OPTIONS] VIDEO_PATH [VIDEO_PATH2 ...]
 
     Upload videos to youtube."""
-    parser = optparse.OptionParser(usage, version=VERSION)
+    parser = optparse.OptionParser(usage)
 
-    # Required options
+    # Video metadata
     parser.add_option('-t', '--title', dest='title', type="string",
         help='Video(s) title')
     parser.add_option('-c', '--category', dest='category', type="string",
         help='Video(s) category')
-
-    # Optional options
     parser.add_option('-d', '--description', dest='description', type="string",
         help='Video(s) description')
     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}])')
     parser.add_option('', '--privacy', dest='privacy', metavar="STRING",
         default="public", help='Privacy status (public | unlisted | private)')
     parser.add_option('', '--location', dest='location', type="string",
         default=None, metavar="latitude=VAL, longitude=VAL, altitude=VAL",
         help='Video(s) location"')
+    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}])')
 
     # Authentication
     parser.add_option('', '--client-secrets', dest='client_secrets',
@@ -208,4 +161,4 @@ def main(arguments):
     run_main(parser, options, args)
 
 if __name__ == '__main__':
-    sys.exit(catch_exceptions(EXIT_CODES, main, sys.argv[1:]))
+    sys.exit(lib.catch_exceptions(EXIT_CODES, main, sys.argv[1:]))