title: Pipeline Media Blocks en JSON : enregistrer et restaurer description: Sérialisez un pipeline Media Blocks en JSON, validez-le, matérialisez-le et capturez un pipeline en cours. Exemples C# avec diagnostics. tags: - Media Blocks SDK - .NET - MediaBlocksPipeline - Windows - macOS - Linux - Android - iOS - GStreamer - JSON - Serialization - C# primary_api_classes: - MediaBlocksPipeline - MediaBlocksPipelineDocument - MediaBlocksPipelineJsonSerializer - MediaBlocksPipelineValidator - MediaBlocksPipelineMaterializer - MediaBlocksPipelineSnapshot - MediaBlockCatalog
Enregistrer et restaurer un pipeline Media Blocks en JSON en C¶
Table des matières¶
- Vue d'ensemble
- Le modèle de document
- Construire un pipeline à partir du JSON
- Valider avant de construire
- Capturer un pipeline en cours
- Chemins de ressources relatifs
- Diagnostics
- Découvrir les types de blocs
- Démos
Vue d'ensemble¶
Un pipeline Media Blocks se construit normalement en code : vous créez les blocs, vous connectez leurs pads et vous démarrez le pipeline. La couche de persistance permet de faire la même chose avec un document — un simple fichier JSON qui nomme les blocs, leurs réglages et leurs connexions. Ce document peut être écrit par votre application, modifié à la main, livré comme préréglage ou produit par un éditeur visuel.
Trois types s'en chargent, chacun avec une seule responsabilité :
| Type | Rôle |
|---|---|
MediaBlocksPipelineJsonSerializer | texte JSON ⇄ MediaBlocksPipelineDocument |
MediaBlocksPipelineValidator | vérifie un document avant toute construction |
MediaBlocksPipelineMaterializer | document → MediaBlocksPipeline vivant |
Le sens inverse — pipeline vivant → document — est assuré par MediaBlocksPipelineSnapshot, accessible via MediaBlocksPipeline.ToDocument().
flowchart LR
JSON[Fichier JSON] -->|Load| Document[MediaBlocksPipelineDocument]
Document -->|Validate| Diagnostics[Diagnostics]
Document -->|Materialize| Pipeline[MediaBlocksPipeline]
Pipeline -->|ToDocument| Document
Document -->|Serialize| JSON Le modèle de document¶
MediaBlocksPipelineDocument est un arbre de DTO simple :
SchemaVersion— la version du format du document. Les versions antérieures sont migrées au chargement.Pipeline—Id,Nameet réglages facultatifs du pipeline.Blocks— unMediaBlockDocumentpar bloc :Id(unGuid),Type(la valeurMediaBlockType),TypeName,Nameet une chargeSettings.Connections— unMediaBlockConnectionDocumentpar connexion, avec une référenceFromet une référenceTode typeMediaBlockPadReference.
Une référence de pad est un identifiant de bloc plus un identifiant de pad, et celui-ci suit une convention unique :
| Identifiant de pad | Signification |
|---|---|
input / output | le pad principal du bloc |
input:N / output:N | l'élément N de la liste Inputs / Outputs du bloc |
La forme indexée est à privilégier lorsque vous générez des documents : elle désigne n'importe quel bloc, alors que la forme sans index exige un pad principal que tous les blocs n'ont pas. Pour un sink multiplexeur comme MP4SinkBlock, input:0 et input:1 sont les flux vidéo et audio.
Un document minimal :
{
"schemaVersion": 1,
"pipeline": { "id": "6f0d1b6e-1f7a-4f1e-9a1a-0a0f3d5f7a11", "name": "Player" },
"blocks": [
{
"id": "10000000-0000-4000-8000-000000000001",
"type": 3,
"typeName": "UniversalSource",
"name": "Media File",
"settings": { "uri": "clips/sample.mp4", "renderVideo": true, "renderAudio": true }
},
{
"id": "10000000-0000-4000-8000-000000000002",
"type": 21,
"typeName": "VideoRenderer",
"name": "Preview"
}
],
"connections": [
{
"from": { "blockId": "10000000-0000-4000-8000-000000000001", "padId": "output:0" },
"to": { "blockId": "10000000-0000-4000-8000-000000000002", "padId": "input" }
}
]
}
Construire un pipeline à partir du JSON¶
Le chemin le plus court remplace le contenu d'un pipeline existant :
var pipeline = new MediaBlocksPipeline();
var result = await pipeline.LoadJsonAsync(
File.ReadAllText("player.json"),
resolver: null,
baseDirectory: Path.GetDirectoryName(Path.GetFullPath("player.json")));
if (!result.Success)
{
foreach (var diagnostic in result.Diagnostics)
{
Console.WriteLine(diagnostic);
}
return;
}
await pipeline.StartAsync();
LoadJsonAsync exige que le pipeline soit arrêté et ne laisse jamais un graphe à moitié construit : si la matérialisation échoue en cours de route, le pipeline est vidé.
Pour construire un pipeline sans en posséder un au préalable, utilisez directement le matérialiseur. Il renvoie le pipeline et la correspondance entre les identifiants du document et les blocs vivants, ce dont vous avez besoin pour atteindre ensuite un bloc :
var loaded = MediaBlocksPipelineJsonSerializer.Load(json);
var result = MediaBlocksPipelineMaterializer.Materialize(loaded.Document, resolver: null, baseDirectory: folder);
if (result.Success)
{
var overlay = (TextOverlayBlock)result.Blocks[captionId];
overlay.Settings.Text = "Live";
}
Valider avant de construire¶
Validate répond aux mêmes questions que la matérialisation, sans rien construire — une interface peut donc afficher les problèmes d'un document pendant que l'utilisateur le modifie :
var diagnostics = MediaBlocksPipelineValidator.Validate(
document,
resolver: null,
baseDirectory: folder);
var errors = diagnostics.Where(d => d.Severity == MediaBlocksDiagnosticSeverity.Error).ToList();
Sont vérifiés : la structure du document, le fait que chaque type de bloc soit connu de cette version, que chaque bloc dispose d'une voie de construction, que les références de pad s'analysent et désignent des pads que le bloc possède réellement, qu'aucun cycle de rétroaction n'existe et — lorsque vous transmettez un baseDirectory — que les fichiers lus par une source soient présents.
Passez baseDirectory: null pour ignorer entièrement les vérifications du système de fichiers ; c'est la valeur par défaut, et elle préserve le comportement d'un document validé avant que ses ressources ne soient en place.
Capturer un pipeline en cours¶
ToDocument() parcourt le graphe vivant et produit un document. L'opération est sûre pendant que le pipeline tourne — la liste des blocs est prise sous le verrou du pipeline et rien n'est modifié —, ce qui en fait la voie d'enregistrement pendant la lecture :
var snapshot = pipeline.ToDocument();
if (!snapshot.Complete)
{
foreach (var diagnostic in snapshot.Diagnostics)
{
Console.WriteLine(diagnostic);
}
}
await MediaBlocksPipelineJsonSerializer.SaveFileAsync(snapshot.Document, "captured.json");
ToJson() et SaveJsonAsync(path) sont les formes en une ligne ; elles envoient les diagnostics au journal du SDK au lieu de les renvoyer.
Le graphe est capturé exactement ; les réglages pas toujours
L'identité, le type et les connexions d'un bloc se lisent sur n'importe quel bloc : la forme d'un pipeline fait donc toujours l'aller-retour. Sa configuration ne se lit que sur les blocs qui exposent leurs réglages — 153 des 404 types de blocs de ce SDK le font. Pour les autres il n'y a rien à lire et, plutôt que d'écrire un document qui paraîtrait complet et reconstruirait le bloc sur ses valeurs par défaut, la capture signale un diagnostic MBS060 et laisse le champ settings de ce bloc vide.
Consultez MediaBlocksPipelineSnapshotResult.Complete avant de considérer une capture comme une copie fidèle. Un pipeline lui-même construit à partir d'un document fait l'aller-retour complet, car la matérialisation inscrit sur les blocs qu'elle crée les identifiants du document.
Chemins de ressources relatifs¶
Les réglages qui nomment un fichier peuvent être relatifs au document. Transmettez le dossier du document comme baseDirectory : la validation comme la matérialisation les résolvent par rapport à lui.
var folder = Path.GetDirectoryName(Path.GetFullPath(documentPath));
var result = MediaBlocksPipelineMaterializer.Materialize(document, resolver: null, baseDirectory: folder);
La réécriture couvre les réglages de type Uri et les réglages de type chaîne nommés *Path, *File, Filename ou *Location. Les valeurs qui désignent un point de terminaison réseau plutôt qu'un fichier sont laissées telles quelles : toute valeur avec un schéma (rtsp://, srt://:8888/), un littéral IPv4, ou un premier segment qui se lit comme un nom d'hôte (cam.local/stream.m3u8). Un dossier dont le nom se lit comme un hôte est ambigu, et le validateur le signale par un avertissement MBS057 ; préfixez cette valeur par ./ pour imposer la lecture « dossier ».
Diagnostics¶
Chaque point d'entrée renvoie des valeurs MediaBlocksDiagnostic au lieu de lever une exception, si bien qu'une application hôte peut afficher toute la liste d'un coup. Chacune porte une Severity, un Code, un Message et le BlockId auquel elle se rapporte.
| Code | Signification |
|---|---|
MBS031 | type de bloc inconnu — le catalogue de cette version ne le contient pas |
MBS032 | le bloc n'a aucune voie de construction |
MBS040 | le bloc n'a pas pu être construit |
MBS048 / MBS054 | une référence de pad n'a pas pu être résolue, ou un pad est utilisé deux fois |
MBS049 | les réglages n'ont pas de constructeur par défaut et le document n'apporte aucune charge utilisable |
MBS050 | la charge de réglages n'a pas pu être désérialisée |
MBS055 | un fichier lu par une source est absent |
MBS056 | une entrée resources n'a pas pu être appliquée |
MBS057 | une valeur qui se lit comme un point de terminaison réseau a été laissée telle quelle |
MBS060 | un bloc n'a pas exposé ses réglages à la capture |
MBS061 | un bloc n'a pas pu être nommé dans la capture |
MBS062 | une connexion n'a pas pu être exprimée dans la capture |
Découvrir les types de blocs¶
MediaBlockCatalog est l'index sur lequel repose la couche de persistance, et il est utile en lui-même : il énumère tous les blocs livrés par cette version, avec leur type de réglages, leurs propriétés modifiables et une sonde de disponibilité.
foreach (var descriptor in MediaBlockCatalog.All)
{
Console.WriteLine($"{descriptor.TypeName} - {descriptor.DisplayName} ({descriptor.Category})");
}
var mp4 = MediaBlockCatalog.Get(MediaBlockType.MP4Sink);
Console.WriteLine(mp4.IsSink); // true - il termine une branche
Console.WriteLine(mp4.AcceptsDynamicInputs); // true - un pad d'entrée par flux
Démos¶
Un exemple console exécutable — construire un pipeline en code, l'enregistrer en JSON, le reconstruire à partir de ce JSON et comparer les deux — est livré avec les exemples du SDK sous Media Blocks SDK / Console.