Giter VIP home page Giter VIP logo

wystia's Introduction

Wystia - Wistia API Helper

image

image

image

image

Documentation Status

Updates

A Python wrapper library for the Wistia API

Installation

The Wystia library is available on PyPI, and can be installed with pip:

$ pip install wystia

You'll also need to create an access token as outlined in the docs.

Usage

Sample usage with the Data API:

Note: The following example makes use of WistiaApi, which is an alias to the class WistiaDataApi.

from wystia import WistiaApi
from wystia.models import SortBy, LanguageCode, Customizations, Private

# Setup the Wistia API token to use for requests. You can alternatively
# set this via the env variable 'WISTIA_API_TOKEN'.
WistiaApi.configure('MY-TOKEN')

# Retrieve a list of all projects in the Wistia account,
# sorted A-Z and in ascending order.
projects = WistiaApi.list_all_projects(SortBy.NAME)
project_ids = [p.hashed_id for p in projects]
# Print the project data as a prettified JSON string
print(projects.prettify())

# Retrieve a list of videos for a Wistia project.
# Note: If you don't require asset info (such as ADs) on each
#   video, I suggest calling `list_project` instead.
videos = WistiaApi.list_videos('project-id')

# Retrieve info on a particular video
vd = WistiaApi.get_video('video-id')
# If the video has captions, that won't be included in the `Medias#show`
# response by default, so we'll need a separate API call as below.
# vd.process_captions(
#     WistiaApi.list_captions(real_video_id))
print(vd)

# Update attributes on a media (video), or set a custom thumbnail on the video.
WistiaApi.update_video(
    'video-id',
    thumbnail_media_id='uploaded-thumbnail-id'
)

# Get aggregated stats for a video, such as view count
stats = WistiaApi.get_stats_for_video('video-id')

# Retrieve the customization data for a video
customizations = WistiaApi.get_customizations('video-id')

# Update only specific customizations for a video
# Note the embed options are documented here:
#   https://wistia.com/support/developers/embed-options
sample_embed_options = Customizations(
    player_color='#e7fad1',
    # Hide comments on the media page
    private=Private(show_comments=False)
)
WistiaApi.update_customizations('video-id', sample_embed_options)

# Get the Spanish captions on a video
captions = WistiaApi.get_captions('video-id', LanguageCode.SPANISH)

# Add (or replace) the English captions on a video
WistiaApi.update_captions(
    'video-id',
    LanguageCode.ENGLISH,
    srt_file='path/to/file.srt'
)

... or to upload media via the Upload API:

from wystia import WistiaUploadApi

# Upload a file to a (default) project on Wistia
r = WistiaUploadApi.upload_file('path/to/my-file.mp4')
# Check if the video was successfully uploaded
# assert r.created
# assert r.name == 'my-file.mp4'

# Uploads with a public link to a video, such as
# an S3 pre-signed url.
r = WistiaUploadApi.upload_link('my-s3-link',
                                title='My Video Name',
                                description='My Description')

... you can alternatively retrieve asset info via the public Media Embed link:

from wystia import WistiaEmbedApi

# Get the media embed data
embed_data = WistiaEmbedApi.get_data('video-id')

# Retrieve the source URL of the original media
source_url = WistiaEmbedApi.asset_url(media_data=embed_data)

... when using the Data API, the WistiaHelper can help to further simplify some calls:

from wystia import WistiaHelper

# Check if the video exists in your Wistia account
assert WistiaHelper.video_exists('abc1234567')

# Check if a video's name indicates the video is an archived copy of an
# existing video, as discussed in the below article on replacing a media:
#   https://wistia.com/learn/product-updates/improved-library-management-tools
assert WistiaHelper.is_archived_video(
    'My Title [Archived on August 13, 2015]')

# Update the player color on a video
WistiaHelper.customize_video_on_wistia('video-id', 'ffffcc')

# Individually enable captions / AD in the player for a video
WistiaHelper.enable_ad('video-id')
WistiaHelper.enable_captions('video-id', on_by_default=False)

# Disable captions / AD in the player for a video
if WistiaHelper.has_captions_enabled('video-id'):
    print('Disabling captions and AD for the video')
    WistiaHelper.disable_captions_and_ad('video-id')

Getting Started

Using the methods on the API classes assume your Wistia API token has previously been configured, for example via the environment. The API token will then be used globally by all the API classes when making requests to the Wistia API.

You can set the following environment variable with your API token:

  • WISTIA_API_TOKEN

Another option is to use the global configure method as shown below:

WistiaDataApi.configure('MY-API-TOKEN')

There is additionally a Quickstart section in the docs which walks through - in more detail - how to get up and running with the Wystia library.

Data API

The wrapper class WistiaDataApi (aliased to WistiaApi) interacts with the Wistia Data API (docs below):

It fully implements the following sections in the API documentation:

  • Paging and Sorting Responses
  • Projects
  • Medias
  • Customizations
  • Captions

The following sections in the API have not been implemented (mainly as I haven't used them before):

  • Project Sharings
  • Account

Tips

Containers

In general, the API methods that begin with list - such as list_project -will return a Container object, which essentially acts as a thin wrapper around a collection of model classes. For all intents and purposes, this behaves exactly the same as a list object.

One of the main benefits is that it implements a __str__ method, which leverages the builtin pprint module in Python to pretty-print the Python object representation of each model or dataclass instance; this will format the output more nicely, for example whenever print(obj) is called on the Container result.

The Container objects also implement the following convenience methods, which can be used to easily display the JSON string representation of the list of dataclass instances:

  • to_json - Convert the list of instances to a JSON string.
  • prettify - Convert the list of instances to a prettified JSON string.

List Medias in a Project

If you need to retrieve info on videos in a project and you don't need complete info such as a list of assets for the video, I recommend using list_project instead of list_videos. This is because the Projects#show API returns up to 500 results per request, whereas the Medias#list only returns the default 100 results per page.

Assuming a project in your Wistia account has a total of about 250 media, here is the number of API calls you might expect from each individual approach:

from wystia import WistiaDataApi

videos = WistiaDataApi.list_videos('project-id')
assert WistiaDataApi.request_count() == 3

# Resets request count for the next call
WistiaDataApi.reset_request_count()

videos = WistiaDataApi.list_project('project-id')
assert WistiaDataApi.request_count() == 1

Thread Safety

The Wistia API classes are completely thread safe, since requests.Session objects are not re-used between API calls.

This means that if you have two (un-related) API operations to perform, such as updating a video's title and adding captions on the video, then you can certainly run those calls in parallel so that they complete a bit faster.

Credits

This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.

wystia's People

Contributors

cb-rnag avatar pyup-bot avatar rnag avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

wystia's Issues

Update for Compatibility with Python 3.5 and 3.6

  • Wistia API Helper version: v0.2.1 (Latest)
  • Python version: v3.5.2
  • Operating System: Custom (like Ubuntu Debian)

Description

Our company has currently been working with a 3rd party provider (Editshare) for our video editing workflow. There is a centralized all-in-one (AIO) Linux server set up as part of the workflow that we have running on EC2. As part of the automations hosted on this server, one of them is an automation script I've set up that will leverage the Wistia API to automatically upload video files on our local EBS volumes (which is used by our video editing team) to our Wistia account.
Right now I've hard-coded a custom implementation of the Wistia Upload API in the script I have running on the server, since I'm unable to import the wystia helper library (which requires Python 3.7 or higher)

Our Linux AIO server has both Python 2 and 3 installed, however the Python 3 version is fixed at v3.5.2. Our team currently doesn't have sudo permissions to upgrade the Python 3 version. I also checked with one of the Editshare team members we are working with, and they confirmed that we don't want to upgrade the Python 3 version because their application might be using scripts that rely on the specific Python version.

To summarize, it'd be great to update this library to support Python versions as far back as 3.5 (by extension that will also add Python 3.6 to the list of supported versions, which is a nice bonus). Personally, the main use case will be so that the automation script which lives on the Linux server (which is limited to use Python 3.5) can import the wystia helper library without any issues, and is able to upload large (>2GB) video files to our video hosting platform of choice, i.e. Wistia, via the WistiaUploadApi helper class.

What I Did

pip install wystia==0.2.1    # the install by itself does succeed without errors

# This import fails due to Python 3.6+ specific code being used in the library -- that includes
# f-strings, dataclasses, basically all the nice-to-have features :)
from wystia import WistiaUploadApi

Automatically be notified of new additions or changes to the Data API

  • Wistia API Helper version: 1.2.2
  • Python version: 3.11.2
  • Operating System: Mac OS X (M1)

Description

It seems that Wistia continuously adds new endpoints to the Data API, or else modifies payloads etc.

Question, is it possible to come up with an automated way to detect such updates/changes, and be notified of it -- via email, or likewise?

I'd like to run a GH Actions script that detects changes or new additions to the API, and then notify me via email periodically, say once a week.

For example, here are some endpoints that are new and which this library currently doesn't support, on account of them being added quite recently:

It would be nice to be notified or find a way to stay up to date of new additions to the API, so that the library can be similarly updated to support those endpoints.

dataclass_wizard.errors.UnknownJSONKey: A JSON key is missing from the dataclass schema for class `Video`. unknown key: 'tags'

  • Wistia API Helper version: Latest
  • Python version: 3.11
  • Operating System: Win 10

Description

Crashed while running my Wistia upload/HTML dump script, which has worked previously. Code here:
https://github.com/KaneDM/wistia-upload-embed/blob/main/tvid.py

The video was uploaded successfully, and the thumbnail was successfully created and assigned, but something went wrong during the thumbnail assignment.

What I Did

Crashed on line 83 of my script, where I call WistiaApi.update_video(vidid, thumbnail_media_id=tn.hashed_id).

Traceback (most recent call last):
  File "D:\Python\tvid.py", line 83, in <module>
    WistiaApi.update_video(vidid, thumbnail_media_id=tn.hashed_id)
  File "C:\Python311\Lib\site-packages\wystia\api_data.py", line 347, in update_video
    return cls.update_media(
           ^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\wystia\api_data.py", line 396, in update_media
    return model_cls.from_dict(r.json())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 536, in fromdict
    return load(d)
           ^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 611, in cls_fromdict
    field_name = lookup_field_for_json_key(o, json_key)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 705, in lookup_field_for_json_key
    raise e from None
dataclass_wizard.errors.UnknownJSONKey: A JSON key is missing from the dataclass schema for class `Video`.
  unknown key: 'tags'
  dataclass fields: ['hashed_id', 'id', 'name', 'type', 'created', 'updated', 'duration', 'status', 'description', 'progress', 'thumbnail', 'project', 'embed_code', 'assets', 'section', 'archived', 'has_audio_description', 'captions_enabled', 'overlay_text', 'caption_duration', 'num_captions', 'ad_disabled']
  input JSON object: {"id": 113495448, "name": "Blep", "type": "Video", "archived": false, "created": "2023-12-22T19:27:51+00:00", "updated": "2023-12-22T19:27:52+00:00", "duration": 1583.04, "hashed_id": "d8wh65z917", "description": "", "progress": 0.14285714285714285, "status": "queued", "thumbnail": {"url": "https://embed-ssl.wistia.com/deliveries/955004dbcdfd7aef4f136c28c495f0df.jpg?image_crop_resized=200x120&video_still_time=791", "width": 200, "height": 120}, "tags": []}

Appears to be the same kind of problem as issue #59.

dataclass_wizard.errors.UnknownJSONKey: A JSON key is missing from the dataclass schema for class `UploadResponse`. unknown key: 'archived'

  • Python version: 3.11
  • Operating System: Windows 10

Description

Attempted to upload a video to Wistia using a script I wrote that has worked in the past. Wystia crashed because the "UploadResponse" class didn't have a way to handle the "archived" key in the JSON returned from the Wistia API.

Fixed it by adding "archived" keys to the "UploadResponse" and "Video" classes in model.py.
Line 244 (Video class):
archived: bool | None = None
Line 744 (UploadResponse class):
archived: bool

What I Did

Initial crash traceback:

Traceback (most recent call last):
  File "D:\Python\tvid.py", line 65, in <module>
    vidupload = WistiaUploadApi.upload_file(vidlatest, project, vidname)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\wystia\api_upload.py", line 74, in upload_file
    return UploadResponse.from_dict(data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 536, in fromdict
    return load(d)
           ^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 611, in cls_fromdict
    field_name = lookup_field_for_json_key(o, json_key)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\site-packages\dataclass_wizard\loaders.py", line 705, in lookup_field_for_json_key
    raise e from None
dataclass_wizard.errors.UnknownJSONKey: A JSON key is missing from the dataclass schema for class `UploadResponse`.
  unknown key: 'archived'
  dataclass fields: ['hashed_id', 'id', 'name', 'type', 'description', 'account_id', 'created', 'updated', 'progress', 'thumbnail', 'duration', 'status']
  input JSON object: {"id": 102354918, "name": "RT Wire Lengths", "type": "Video", "archived": false, "created": "2023-03-17T15:35:37+00:00", "updated": "2023-03-17T15:35:37+00:00", "duration": 1199.032022, "hashed_id": "malb60y0o2", "description": "", "progress": 0.125, "status": "queued", "thumbnail": {"url": "https://embed-ssl.wistia.com/deliveries/a3b1fbd6df17258c467c27207d45a1c5.jpg?image_crop_resized=200x120&video_still_time=599", "width": 200, "height": 120}, "account_id": 392724}

Support API Paths for New Docs

New Docs:
https://docs.wistia.com/reference

As Wistia seems to have rehauled their docs page and changed link + added new API routes, I'd like to update library to stay abreast of that. By updating methods under API classes to add new methods to call those routes. Also add test cases if possible.

Initial Update

The bot created this issue to inform you that pyup.io has been set up on this repo.
Once you have closed it, the bot will open pull requests for updates as soon as they are available.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.