podgen.Media

class podgen.Media(url, size=0, type=None, duration=None, requests_session=None)[source]

Data-oriented class representing a pointer to a media file.

A media file can be a sound file (most typical), video file or a document.

You should provide the absolute URL at which this media can be found, and the media’s file size in bytes.

Optionally, you can provide the type of media (expressed using MIME types). When not given in the constructor, it will be found automatically by looking at the url’s file extension. If the url’s file extension isn’t supported by iTunes, you will get an error if you don’t supply the type.

You are also highly encouraged to provide the duration of the media.

Note

iTunes is lazy and will just look at the URL to figure out if a file is of a supported file type. You must therefore ensure your URL ends with a supported file extension.

Note

A warning called NotSupportedByItunesWarning will be issued if your URL or type isn’t compatible with iTunes. See the Python documentation for more details on warnings.

Media types supported by iTunes:

  • Audio
    • M4A
    • MP3
  • Video
    • MOV
    • MP4
    • M4V
  • Document
    • PDF
    • EPUB

All attributes will always have a value, except size which can be 0 if the size cannot be determined by any means (eg. if it’s a stream) and duration which is optional (but recommended).

See also

Enclosing media
for a more gentle introduction.
classmethod create_from_server_response(url, size=None, type=None, duration=None, requests_=None)[source]

Create new Media object, with size and/or type fetched from the server when not given.

See Media.fetch_duration() for a (slow!) way to fill in the duration as well.

Example (assuming the server responds with Content-Length: 252345991 and Content-Type: audio/mpeg):

  >>> from podgen import Media
  >>> # Assume an episode is hosted at example.com
  >>> m = Media.create_from_server_response(
  ...     "http://example.com/episodes/ep1.mp3")
  >>> m
  Media(url=http://example.com/episodes/ep1.mp3, size=252345991,
type=audio/mpeg, duration=None)
Parameters:
Returns:

New instance of Media with url, size and type filled in.

Raises:

The appropriate requests exceptions are thrown when networking errors occur. RuntimeError is thrown if some information isn’t given and isn’t found in the server’s response.

download(destination)[source]

Download the media file.

This method will block until the file is downloaded in its entirety.

Note

The destination will not be populated atomically; if you need this, you must give provide a temporary file as destination and rename the file yourself.

Parameters:destination (fd or str.) – Where to save the media file. Either a filename, or a file-like object. The file-like object will not be closed by PodGen.
duration

The duration of the media file.

Type:datetime.timedelta
Raises:TypeError if you try to assign anything other than datetime.timedelta or None to this attribute. Raises ValueError if a negative timedelta value is given.
duration_str

duration, formatted as a string according to iTunes’ specs. That is, HH:MM:SS if it lasts more than an hour, or MM:SS if it lasts less than an hour.

This is just an alternate, read-only view of duration.

If duration is None, then this will be None as well.

Type:str
fetch_duration()[source]

Download Media.url locally and use it to populate Media.duration.

Use this method when you don’t have the media file on the local file system. Use populate_duration_from() otherwise.

This method will take quite some time, since the media file must be downloaded before it can be analyzed.

file_extension

The file extension of url. Read-only.

Type:str
get_type(url)[source]

Guess the MIME type from the URL.

This is used to fill in type when it is not given (and thus called implicitly by the constructor), but you can call it yourself.

Example:

>>> from podgen import Media
>>> m = Media("http://example.org/1.mp3", 136532744)
>>> # The type was detected from the url:
>>> m.type
audio/mpeg
>>> # Ops, I changed my mind...
>>> m.url = "https://example.org/1.m4a"
>>> # As you can see, the type didn't change:
>>> m.type
audio/mpeg
>>> # So update type yourself
>>> m.type = m.get_type(m.url)
>>> m.type
audio/x-m4a
Parameters:url (str) – The URL which should be used to guess the MIME type.
Returns:The guessed MIME type.
Raises:ValueError if the MIME type couldn’t be guessed from the URL.
populate_duration_from(filename)[source]

Populate Media.duration by analyzing the given file.

Use this method when you have the media file on the local file system. Use Media.fetch_duration() if you need to download the file from the server.

Parameters:filename (str) – Path to the media file which shall be used to determine this media’s duration. The file extension must match its file type, since it is used to determine what type of media file it is. For a list of supported formats, see https://pypi.python.org/pypi/tinytag/
requests_session = None

The requests.Session object which shall be used. Defaults to a new session with PodGen as User-Agent.

This is used by the instance methods download() and fetch_duration(). create_from_server_response(), however, creates its own requests Session if not given as a parameter (since it is a static method).

You can set this attribute manually to set your own User-Agent and benefit from Keep-Alive across different instances of Media.

Type:requests.Session
size

The media’s file size in bytes.

You can either provide the number of bytes as an int, or you can provide a human-readable str with a unit, like MB or GiB.

An unknown size is represented as 0. This should ONLY be used in exceptional cases, where it is theoretically impossible to determine the file size (for example if it’s a stream). Setting the size to 0 will issue a UserWarning.

Type:str (which will be converted to and stored as int) or int

Note

If you provide a string, it will be translated to int when the assignment happens. Thus, on subsequent accesses, you will get the resulting int, not the string you put in.

Note

The units are case-insensitive. This means that the B is always assumed to mean “bytes”, even if it is lowercase (b). Likewise, m is taken to mean mega, not milli.

type

The MIME type of this media.

See https://en.wikipedia.org/wiki/Media_type for an introduction.

Type:str

Note

If you leave out type when creating a new Media object, the type will be auto-detected from the url attribute. However, this won’t happen automatically other than during initialization. If you want to autodetect type when assigning a new value to url, you should use get_type().

url

The URL at which this media is publicly accessible.

Only absolute URLs are allowed, so make sure it starts with http:// or https://. The server should support HEAD-requests and byte-range requests.

Ensure you quote parts of the URL that are not supposed to carry any special meaning to the browser, typically the name of your file. Common offenders include the slash character when not used to separate folders, the hash mark (#) and the question mark (?). Use urllib.parse.quote() in Python3 and urllib.quote() in Python2.

Type:str