Frame.io API

Frame.io API Documentation

Welcome to Frame.io's official documentation portal.In here, you'll find everything you need to:

Get up and running with Frame.io's public API 🤙
Leverage powerful features like Webhooks and Custom Actions 🚀
Build your own OAuth2.0 app 🚢

Get Started    Guides

Scrape All Comments from a Project

This guide discusses how to scrape comments from a project and output them into a .csv file. This is useful for situations where someone wants to see all the comments on a project and what assets someone commented on. You can use the .csv file to send content to other tools and applications.

Get a code sample

You can check out the comment scraper on Github: Comment Scraper in Python

Try the comment scraper now

If you want to see the comment scraper work on a server, we have a Flask app set up on Glitch. Glitch allows you to set up your own applications and test and run them using their servers. If you're not familiar with Glitch, or you want some tips for setting it up for use with Python (Glitch does not officially support Python), check out our guide Get Started with Glitch.

You can see the Glitch code sample for the comment scraper here: Frame.io Comment Scraper in Python

How to Set up the Comment Scraper

The comment scraper will retrieve all assets in a project, scrape the comments, and output them in a .csv file. This walkthrough uses the following resources:

  • Python SDK - The SDK handles pagination for you, and sets up a client you can use with developer tokens (bearer authentication).
  • Comment scraper in Python - The code sample we are using is here.

The general instructions for creating your own comment scraper are:

  1. Sign in to developer.frame.io using your Frame.io account.

  2. Create a developer token. We recommend that you create the token with all scopes to start with. You can remove scopes later by creating different tokens as needed. Instructions are provided in Set up Bearer Token Authentication (Developer Tokens)

  3. Log in to the Frame.io app. If you're on a free trial, you'll see a demo project, you can use that to try the comment scraper. Add a few comments to the project. Otherwise choose the project you want to use with the comment scraper.

  4. Grab the root asset ID for the project you want to scrape comments for. (root_asset_id) If you need help, use these instructions: Retrieve the Root Asset ID for a Project. The root asset ID is a special ID for a project that represents the container for everything in your entire project. You use this as a reference point to retrieve details about the rest of the project. In order to get it you'll need to start by retrieving the account IDs available to your developer token.

  5. Set up the basics for your app, such as what you'll need to import and any global variables.

from frameioclient import FrameioClient
import requests, json, csv, itertools

ROOT_ASSET_ID = "Put your root asset ID here."
TOKEN = "Put your developer token here."
  1. Next you'll want to use the root asset ID to retrieve the first set of assets. You'll want to recursively retrieve all assets, check them for comments, and store any assets you find in a list when they have comments.

📘

NOTE:

You need a way to check whether what comes back is paginated each time, and you'll need to retrieve all the pages. (Or use the Python SDK which handles it for you.)

After retrieving the first set of assets, you switch from retrieving assets with root_asset_id to retrieving them with just an id.

An easy way to set up is to create a function that will return a list of all your project comments. In our walkthrough, we're calling it get_all_project_comments. It takes an ID and a token, sets up a client and a list that it will return with all the commented assets.

To handle the assets, create a function all_comments that will be called by get_all_project_comments. You'll need a way to handle each asset type in all_comments. Frame.io has three asset types to consider:

  • file - a file has no children and represents something like a video clip or an image.
  • version_stack - a version stack is a stack of files where each item in the stack is a different version. This is similar to a folder in that you can retrieve the version stack as a list of files. It also has no children.
  • folder - a folder may or may not have children. Typically, they do.

You can see from the example that all_comments(client, asset_id, comment_list) takes the client you initialized in get_all_project_comments, as well as the ID to use for retrieving assets, and the list you want to append comments to.

For every asset in the list of assets you retrieve, you do the following checks:

  • Check if something is a file.
    • If it's a file, check if it has comments.
      • If it has comments, save the parent ID (parent_id) for the asset and the name of the asset (asset_name).
      • Retrieve all the comments, and for every comment, add the parent ID and the asset name to it. Later, you can use this for context to figure out where the comment was easily. This information is not included with the comment, which is why you add it.
      • Add the comment to your list.
  • Check if something is a folder.
    • If it's a folder, then run all_comments again.
  • Check if something is a version stack.
    • If it's a version stack, then get all the children.
      • Check each child the same way you did for files.
      • Add children with comments to your list and include the asset name and parent ID for each comment.
def all_comments(client, asset_id, comment_list):
    files = client.get_asset_children(asset_id)

    for asset in files:
        if asset['type'] == "file":
            if asset['comment_count'] > 0:
                asset_parent_id = asset['parent_id']
                asset_name = asset['name']
                comments = client.get_comments(asset['id'])
                my_comment_list = [comment for comment in comments.results]
                for object in my_comment_list:
                    object.update({'parent_id':asset_parent_id})
                    object.update({'name':asset_name})
                comment_list.append(my_comment_list)

        if asset['type'] == "folder":
            if asset['item_count'] > 0:
                all_comments(client, asset['id'], comment_list)

        if asset['type'] == "version_stack":
            asset_name = asset['name']
            parent_id = asset['parent_id']
            vfiles = client.get_asset_children(asset['id'])

            for asset in vfiles.results:
                asset_name = asset['name']
                parent_id = asset['parent_id']
                if asset['type'] == "file":
                    if asset['comment_count'] > 0:
                        comments = client.get_comments(asset['id'])
                        my_comment_list = [comment for comment in comments.results]
                        for object in my_comment_list:
                            object.update({'parent_id':parent_id})
                            object.update({'name':asset_name})
                        comment_list.append(my_comment_list)

def get_all_project_comments(root_asset_id, token):
    comment_list = []
    client = FrameioClient(token)

    all_comments(client, root_asset_id, comment_list)

    return comment_list

📘

NOTE:

Don't forget to handle pagination for each asset type.

  1. Once you have a complete list of comments, you'll want to flatten out your list (if you chose not to during the retrieval).
# The response list comes back as a list of lists.
# Flatten out responses so that there's only one item in each part of the list

flat_response_list = list(itertools.chain.from_iterable(responses))
  1. When your list is flat, you can use list comprehension to grab the elements from each comment that you think are useful, and then output them into a .csv file. We recommend at least having:
    • Comment - text
    • Parent ID - parent_id
    • Asset ID - asset_id
    • Asset Name name - however, in order to get this, you'll have to grab it from what comes back with the asset information and then add it to what comes back for comments. Asset Name is not provided when you retrieve comment information.
    • Owner ID - owner_id
    • Owner Email - [owner][`email`]
    • Timestamp - timestamp
    • Updated At - updated_at
list_for_csv = [[o['text'], o['parent_id'], o['asset_id'], o['name'], o['owner_id'], o['owner']['email'], o['timestamp'], o['updated_at']] for o in flat_response_list]

You can add or remove items as you see fit by looking through the API response to see which parameters you might want, or by looking through the API reference.

  1. When you've made a new list containing the output you want per asset for your .csv file, it's time to write to your .csv file.
# Let's write our new list out to a .csv file. We'll add a heading.
with open("output.csv", 'w') as myfile:
     wr = csv.writer(myfile, dialect='excel')
     wr.writerow(['Comment', 'Parent ID', 'Asset ID', 'Asset Name', 'Owner ID', 'Email', 'Timestamp', 'Updated At'])
     wr.writerows(list_for_csv)

And that's the comment scraper. You can use this walkthrough to make your own or grab this one for use somewhere.

Updated 3 months ago

Scrape All Comments from a Project


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.