Présentation des actions personnalisées

<Info title=“Exemples d’applications”>

Si vous souhaitez créer votre propre application d’actions personnalisées, nos exemples d’applications vous aideront à commencer :

</Info>

Les actions personnalisées vous permettent d’intégrer des éléments directement dans Frame.io sous forme de composants d’interface utilisateur programmables. Cela permet toute une classe de processus qui peuvent être déclenchés par les utilisateurs dans l’application, en tirant profit du même routage d’événements sous-jacent que les Webhooks. Actuellement, les actions personnalisées sont disponibles pour les ressources et s’affichent dans le menu déroulant contextuel / clic droit disponible sur toute ressource, comme illustré dans l’image ci-dessous. <img alt=“actions-1” src=“file:docs/pages/v2/images/actions-1.png”>

Un asset est une représentation robuste d’un fichier dans S3, et de son contexte dans Frame.io. Cela inclut les transcodages, le contexte utilisateur/équipe/projet et les métadonnées. Lorsqu’un utilisateur clique sur une action personnalisée sur un asset, Frame.io enverra une charge utile à une URL que vous fournissez. L’application de réception peut alors répondre avec un code d’état HTTP pour simplement accuser réception, ou peut répondre avec un rappel personnalisé qui peut afficher une interface utilisateur supplémentaire dans Frame.io.

Configurez votre action personnalisée

<Info title=“Vérifiez vos autorisations”>

Des autorisations de gestionnaire d’équipe sont nécessaires pour créer des actions client pour une équipe. Demandez à l’administrateur de modifier les autorisations si vous n’avez pas accès.

</Info> Des actions personnalisées peuvent être configurées dans la zone Actions personnalisées de developer.frame.io. Une action nécessite :

Nom du champDescription
NomLe nom que vous choisissez pour votre action personnalisée. Il s’affichera dans le menu des actions personnalisées disponibles dans Frame.io.
DescriptionExpliquez ce que fait l’action, pour référence (la description n’apparaîtra pas dans l’appli web Frame.io).
ÉvénementClé d’événement interne pour vous aider à différencier les événements webhook standard et les vôtres.
URLOù livrer les événements.
ÉquipeL’équipe qui utilisera l’action personnalisée.

Cliquez sur - Ce qu’il y a dans la charge utile que vous recevez de Frame.io

Lorsque l’utilisateur clique sur votre action personnalisée, une charge utile sera envoyée à l’URL que vous avez spécifiée dans le champ URL.

1POST /your/url
2\{
3 "action_id": "2444cccc-7777-4a11-8ddd-05aa45bb956b",
4 "interaction_id": "aafa3qq2-c1f6-4111-92b2-4aa64277c33f",
5 "project": \{
6 "id": "a7d6a74b-d45d-4019-9069-24651e0b9f64"
7 },
8 "resource": \{
9 "id": "9q2e5555-3a22-44dd-888a-abbb72c3333b",
10 "type": "asset"
11 },
12 "team": \{
13 "id": "54353cd2-c6ee-4aa1-954a-ce9e19602aa9"
14 },
15 "type": "my.action",
16 "user": \{
17 "id": "fb57eee0-79f2-4bc7-9b70-99fbc175175c"
18 }
19}

Vous pouvez utiliser cette charge utile pour identifier :

  • Laquelle de vos actions personnalisées a été cliquée
  • Quelle ressource a été cliquée
  • Quel utilisateur a effectué l’action
Nom du champDescription
action_idL’identifiant unique de cette action.Il sera toujours le même pour une action donnée.
interaction_idIl s’agit d’un identifiant unique généré par Frame.io que vous pouvez utiliser pour suivre la transaction.Cet identifiant sera le même tout au long d’une séquence unique d’une action, y compris les formulaires de rappel.
typeLe nom de l’événement que vous avez saisi dans le champ Événement lors de la configuration de votre action.
resource.idL’identifiant de la ressource à partir de laquelle vous avez déclenché votre action (généralement un fichier).
resource.typeLe type de ressource à partir de laquelle vous avez déclenché votre action (généralement asset)

<Info title=“À propos des interactions”> Le interaction_id est fourni comme identifiant unique pour vous aider à suivre l’évolution de l’interaction dans le temps. Si vous n’avez pas besoin de répondre à l’utilisateur, renvoyez simplement un code d’état 200, et c’est terminé. Bien qu’optionnel, nous recommandons d’inclure quelques informations sur le résultat de l’action, comme un simple message de réussite ou une alerte d’erreur. Les actions personnalisées prennent en charge les rappels de messages. </Info>

<Info title=“Nouvelles tentatives et délais d’expiration”>

Notre application attend une réponse en moins de 5 secondes et tentera de relancer jusqu’à 5 fois en attendant une réponse réussie. Vous devriez idéalement répondre immédiatement et effectuer les actions de manière asynchrone après déclenchement via une action personnalisée.

</Info>

Créer un rappel de message

Dans votre réponse HTTP à l’événement webhook, vous pouvez renvoyer un objet JSON décrivant un message qui sera renvoyé à l’utilisateur initiateur dans l’interface utilisateur Frame.io. Si vous souhaitez essayer de créer un message et voir à quoi il ressemblera, vous pouvez essayer notre Custom Action Builder, qui vous permet de configurer des rappels de messages ou des formulaires et voir comment ils apparaîtraient dans l’app web Frame.io.

Voici un exemple d’objet :

1\{
2 "title": "Success!",
3 "description": "The thing worked! Nice."
4}

Cela affichera une alerte à l’utilisateur qui ressemble à ceci :

<img alt=“actions-3” src=“file:docs/pages/v2/images/actions-3.png”>

Les messages sont un moyen simple de boucler le cycle de vie de l’action d’une manière qui fournit un contexte variable à l’utilisateur agissant, sans lui demander de changer de contexte.

Cela suffit à satisfaire de nombreux cas d’utilisation, mais parfois la charge utile initiale et les appels ultérieurs à l’API Frame.io ne fourniront pas suffisamment de contexte pour l’application réceptrice. Pour ces scénarios, nous prenons également en charge les Form Callbacks.

Créer un rappel de formulaire

Disons que vous avez besoin de plus d’informations avant de commencer votre processus. Par exemple, vous pourriez charger du contenu vers un système qui nécessite des détails et paramètres supplémentaires. Vous pouvez « décrire » un formulaire dans votre réponse, que l’utilisateur verra réellement ! Et qu’il remplira ! Et il vous sera renvoyé directement !

Voici un exemple de formulaire qui générera un formulaire dans l’interface utilisateur Frame.io que l’utilisateur agissant initial peut remplir et soumettre :

1\{
2 "title": "Need some more info!",
3 "description": "Getting ready to submit this file!",
4 "fields": [
5 \{
6 "type": "text",
7 "label": "Title",
8 "name": "title",
9 "value": "MyVideo.mp4"
10 },
11 \{
12 "type": "select",
13 "label": "Captions",
14 "name": "captions",
15 "options": [
16 \{
17 "name": "Off",
18 "value": "off"
19 },
20 \{
21 "name": "On",
22 "value": "on"
23 }
24 ]
25 }
26 ]
27}

<img alt=“actions-form” src=“file:docs/pages/v2/images/actions-form.png”>

Lorsque l’utilisateur soumet le formulaire, vous recevez un événement sur la même URL que le POST initial :

1POST /your/url​
2\{
3 "type": "your-specified-event-name",
4 "interaction_id": "the-same-id-as-before",
5 "action_id": "unique-id-for-this-custom-action",
6 "data":\{
7 "title": "MyVideo.mp4",
8 "captions": "off"
9 }
10}

Tous les champs personnalisés que vous avez ajoutés sur votre formulaire apparaissent dans la section data de la charge utile JSON envoyée par Frame.io Utilisez interaction_id pour mapper la demande initiale et ces nouvelles données de formulaire. Et encore une fois, si vous le souhaitez, vous pouvez répondre avec un message (ou même un autre formulaire !).

En enchaînant les Actions, les Formulaires et les Messages, vous pouvez programmer efficacement des workflow d’asset complets dans Frame.io avec la logique métier d’un système externe.

Faites preuve d’imagination ! Tout est possible.

Détails du formulaire

Comme les messages, les Formulaires prennent en charge les attributs title et description qui s’affichent en haut du Formulaire. En plus de cela, chaque champ de formulaire accepte les attributs de base suivants :

  • type — Indique à l’interface utilisateur Frame.io quel type de données attendre, et quel composant et rendu utiliser.
  • label — Apparaît sur l’interface utilisateur comme l’en-tête au-dessus du champ.
  • name — Clé par laquelle le champ sera identifié sur la charge utile ultérieure.
  • value — Valeur avec laquelle pré-remplir le champ.

Types de champs pris en charge

Champ de texte

Un simple champ de texte sans paramètres supplémentaires.

1\{
2 "type": "text",
3 "label": "Title",
4 "name": "title",
5 "value": "MyVideo.mp4"
6}

Zone de texte

Une simple zone de texte sans paramètres supplémentaires.

1\{
2 "type": "textarea",
3 "label": "Description",
4 "name": "description",
5 "value": "This video is really, really popular."
6}

Select list Defines a picklist that the user can choose from. Must include an options list, each member of which should include a human-readable name, and a machine-parseable value.

1\{
2 "type": "select",
3 "label": "Captions",
4 "name": "captions",
5 "value": "off",
6 "options": [
7 \{
8 "name": "Off",
9 "value": "off"
10 },
11 \{
12 "name": "On",
13 "value": "on"
14 }
15 ]
16}

**Liste de sélection** Définit une liste de choix dans laquelle l'utilisateur peut faire une sélection. Doit inclure une listeoptions, dont chaque membre doit inclure un namelisible par l'humain, et unevalue` analysable par la machine. ```json

{

“type”: “select”,

“label”: “Captions”,

“name”: “captions”,

“value”: “off”,

“options”: [

{

“name”: “Désactivé”,

“value”: “off”

},

{

“name”: “Activé”,

“value”: “on”

}

]

}

## Actions personnalisées et modèle d'autorisations Frame.io
Les Webhooks et Actions personnalisées ont un modèle d'autorisations spécial : ils appartiennent à une **équipe**, pas à un utilisateur spécifique qui existe dans une équipe ou un compte. Cela signifie :
* Tout administrateur ou gestionnaire d'équipe peut créer une Action personnalisée dans une équipe.
* Tout administrateur ou gestionnaire d'équipe peut modifier ou supprimer une Action personnalisée qui existe dans une équipe. Une fois modifiée, tous les utilisateurs voient immédiatement le résultat du changement.
## Sécurité
Par défaut, toutes les Actions personnalisées ont une clé de signature générée lors de leur création. Ceci n'est pas configurable. Cette clé peut être utilisée pour vérifier que la requête provient de Frame.io.
### Vérification
Inclus dans la requête `POST` se trouvent les éléments suivants
| Nom | Description |
| ---------- | ---------- |
| X-Frameio-Request-Timestamp\<code>` | L'heure à laquelle votre Action personnalisée a été déclenchée. |
| X-Frameio-Signature`` | La signature calculée. |
**La date et heure** correspond au moment où la requête a été signée en sortant du réseau Frame.io. Ceci peut être utilisé pour empêcher les attaques par rejeu. Nous recommandons de vérifier que cette heure se situe dans les 5 minutes de l'heure locale. **La signature** est un hachage HMAC SHA-256 utilisant la clé de signature fournie lors de la première création de l'Action personnalisée.
#### Vérification de la signature
1. Extraire la signature des en-têtes HTTP
2. Créer un message à signer en combinant la version, l'heure de diffusion et le corps de la requête
* \</code>v0:timestamp:body`
3. Calculer la signature HMAC SHA256 en utilisant votre secret de signature.
* Remarque : La signature fournie est préfixée avec `v0=`. Actuellement, Frame.io n'a que cette seule version pour signer les requêtes. Vous devrez ajouter ce préfixe à votre signature calculée.
4. Comparez !
```python title="Python"
import hmac
import hashlib
def verify_signature(curr_time, req_time, signature, body, secret):
"""
Verify webhook/custom action signature
:Args:
curr_time (float): Current epoch time
req_time (float): Request epoch time
signature (str): Signature provided by the frame.io API for the given request
body (str): Custom Action body from the received POST
secret (str): The secret for this Custom Action that you saved when you first created it
"""
if int(curr_time) - int(req_time) \< 500:
message = 'v0:\{}:\{}'.format(req_time, body)
calculated_signature = 'v0=\{}'.format(hmac.new(
bytes(secret, 'latin-1'),
msg=bytes(message, 'latin-1'),
digestmod=hashlib.sha256).hexdigest())
if calculated_signature == signature:
return True
return False