BLAM3.SDK 3.1.4.8

There is a newer version of this package available.
See the version list below for details.
dotnet add package BLAM3.SDK --version 3.1.4.8
NuGet\Install-Package BLAM3.SDK -Version 3.1.4.8
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BLAM3.SDK" Version="3.1.4.8" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add BLAM3.SDK --version 3.1.4.8
#r "nuget: BLAM3.SDK, 3.1.4.8"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install BLAM3.SDK as a Cake Addin
#addin nuget:?package=BLAM3.SDK&version=3.1.4.8

// Install BLAM3.SDK as a Cake Tool
#tool nuget:?package=BLAM3.SDK&version=3.1.4.8

Blue Lucy SDK

Blue Lucy is a media services integration platform that unifies production and supply chain operations for the media industry. The Blue Lucy .Net SDK provides the coding framework for developers to create their own BLidgets and Plugins for running within the Blue Lucy Workflow Runner. It can also be used to rapidly delevop bespoke integrations directly with the Blue Lucy API.

Blue Lucy SDK Logo

NuGet Packages

Package Latest Version
Blue Lucy.SDK NuGet

Documentation

This README provides a quick overview of how to make use of the Blue Lucy .Net SDK. You can check out some sample code on our public GitHub repository for more in depth examples.

Quick Start

IMPORTANT To use the Blue Lucy .Net SDK, you will need to have an active application account on a Blue Lucy system. Please contact support, or your system adminstrator for assistance in setting up an account on your system.

To get started, first add the BLAM3.SDK package to your project by running the following command:

dotnet add package BLAM3.SDK

You can now create a BlamClient using your application credentials and begin searching your media:

// Create a new BlamClient instance using application credentials
var blamClient = new BlamClient(new BlamClientConfig
{
    BlamApiEndpoint = "https://<your>.bluelucy.com/api",
    Username = "<ApplicationUserName>",
    Password = "<ApplicationPassword>"
});

// Search for the first 100 video assets
var results = await blamClient.Search(new SearchQueryInputModel
{
    Query = "type=video",
    Limit = 100
});

// Select first asset from search results
var asset = results.Items.First();

Update asset metadata

// Create a new metadata snapshot updating just the specified values
var snapshot = await blamClient.CreateMetadataSnapshot(new AssetMetadataSnapshotInputModel
{
    AssetId = asset.Id,
    Values = new Dictionary<string, object>
    {
        { "show_name", "Cats on Air" },
        { "vtr", 899223 },
        { "language", "Dutch" },
        { "tx_date", "2033-01-01T15:00:00+01:00" },
        { "for_broadcast", true }
    },
    Merge = true
});

Updating the metadata on an asset creates a new snapshot version. Creating a snapshot with Merge = true will use the current metadata as the snapshot base and replace just the specified values.

Add an asset to a folder

// Search for an existing folder
var folders = await blamClient.Search(new FolderQueryInputModel
{
    Query = "name=Cats on Air",
    Limit = 1,
    Depth = FolderStructureDepth.Contents
});

// Select first folder from search results
var folder = folders.Items.First();

// Attach the asset to the folder
await blamClient.AttachAssetsToFolder(new FolderAssetListInputModel
{
    FolderId = folder.Id,
    AssetIds = [asset.Id]
});

Assets can be added or removed in bulk by providing a collection of asset Ids.

// Create a temporary link to the proxy file
var link = await blamClient.CreateStreamToken(new StreamTokenRequestInputModel
{
    Asset = new AssetSelectorInputModel { AssetId = asset.Id, Selector = "Current Version;Browse" },
    MaxAllowedClaims = MaxAllowedClaims.Unlimited,
    ShortUrl = true
});

// Use the url for streaming
var url = link.Url;

Links can be single or multi-use and a sharable with external users or processes (e.g. transcoding into different formats).

Triggering a workflow

// Fetch the list of available workflows
var blueprints = await blamClient.GetWorkflowBlueprints();
var blueprint = blueprints.First(b => b.Name == "Deliver Asset to S3");

// Trigger the selected workflow blueprint
var run = await blamClient.TriggerWorkflow(blueprint.Id, new WorkflowRunInputModel
{
    Name = "Delivery for <Customer>",
    Type = BlidgetDataType.Assets,
    Data = new AssetsIO { AssetIds = [asset.Id] }
});

// Check the current state of the workflow run
var runState = await blamClient.GetWorkflowRun(run.Ids.First());
while (runState.Status != WorkflowRunStatus.Complete)
{
    // ...
}

IMPORTANT Workflows can be highly customised per platform. You should contact your workflow administrator to understand what workflows you have access to on your platform. Access to some workflows can be restricted based on your account group access permissions.

BLidgets

BLidgets are short lived micro-processes executed as steps within a Blue Lucy workflow. A BLidget represents a "unit of work" within a workflow and its scope limited to a single task during execution (e.g. Transcode video, Copy file, Import metadata, Run job etc.)

The Blue Lucy SDK simplifies BLidget creation by providing an inheritable base class which implements the BLidget control flow and handles the passing of messages between the BLidget process and the Workflow runner.

BLidget control flow is broken down into 3 phases; Init, Run and Complete:

// ExampleBlidget implements base class `Blidget` with I/O of type `AssetsIO`
internal class ExampleBlidget : Blidget<AssetsIO, AssetsIO>
{
    private BlamClient _client;
    private ExampleState _runState;

    // INIT PHASE - runs on every blidget run
    protected override void Init(AssetsIO inputData)
    {
        _client = new BlamClient();                 // Initialise BlamClient (inherits configuration from the Workflow runner)
        _runState = GetRunState<ExampleState>();    // Initialise or retrieve the current saved run state
    }
    
    // INIT PAHSE - runs on every blidget run (asynchronous variant of `void Init(...)`)
    // protected override Task InitAsync(AssetsIO inputData)
    // {
    //     // Asynchronous init operations
    // }

    // RUN PHASE - runs on the first BLidget execution only, skipped after waking up from `Waiting` or `Idle`
    protected override async Task<BlidgetOutput<AssetsIO>> RunAsync(AssetsIO inputData)
    {
        // Fetch BLidget configuration value
        var nameTemplate = GetArgument<string>("name_template");

        foreach (var assetId in inputData.AssetIds)
        {
            // Fetch input resources
            var asset = await _client.GetAssetById(assetId);

            // Use interpolator to resolve runtime values
            var name = await Interpolate(nameTemplate, _client, new TemplateData { Asset = asset });

            // Do work ...

            // Add data to the run state
            var job = new Job { Uuid = Guid.NewGuid() };
            _runState.Jobs.Add(job);
                
            // Log Debug message
            LogDebug("Added job with ID: '{id}'", job.Uuid);
        }

        // End process and save current run state; wake again once time has elapsed or receiving a call back
        return Waiting(_runState, pollingIntervalSeconds: PollingInterval.OneHour, message: "Waking again in one hour.");

        // or return Idle(_runState, _runState.Jobs.Select(j => new Callback("jobId", $"{j.Uuid}")), message: "Waking on callback.");
        // or return Complete(inputData);
    }

    // COMPLETE PHASE - called each time the BLidget runs after waking up from `Waiting` or `Idle`
    protected override async Task<BlidgetOutput<AssetsIO>> CompleteAsync(AssetsIO inputData)
    {
        // Loop through jobs and update run state
        foreach (var job in _runState.Jobs)
        {
            // Do work ...

            // Update progress state (used to report progress)
            UpdateProgress(50, "Processed 1 of 2 job(s).");
        }

        // Complete process and pass on output data
        return Complete(inputData, message: $"Processed {_runState.Jobs.Count} job(s).");

        // or return Waiting(_runState, pollingIntervalSeconds: PollingInterval.OneHour, message: "Waking again in one hour.");
        // or return Idle(_runState, _runState.Jobs.Select(j => new Callback("jobId", $"{j.Uuid}")), message: "Waking on callback.");
    }
}

internal class ExampleState
{
    public List<Job> Jobs { get; set; } = [];
}

internal class Job
{
    public Guid Uuid { get; set; }
}

More detailed examples can be found on the samples GitHub repository.

Plugins

Plugins are long running processes which are commonly used for watching for and reacting to internal or external events (e.g. files moving into a folder, a timer elapsing, receiving a message). They can also be used as extensions to the API by implementing additional end points or even act as web server for custom UIs.

Plugins implement the .Net IHostedService and provide two methods for control flow; OnStart and OnStop. Additional services or middleware can also be added using .Net's Dependency Injection allowing developers to create fully featured services within a single Plugin.

There are two possible builder patterns depending on whether a web server is required:

Service Pattern

// ExamplePlugin implements base class `PluginInitialiser`
internal class ExamplePlugin : PluginInitialiser
{
    private async Task CreateHostedService()
    {
        var builder = new HostBuilder()
            .ConfigureAppConfiguration((hostContext, configuration) =>
            {

            })
            .ConfigureServices((hostContext, services) =>
            {   // Configure serivces using dependency injection
                services.AddSingleton<BlamClient>();
                services.AddHostedService<ExamplePluginService>();
            });

        var host = builder
            .Build();

        // Runs hosted service(s)
        await host.RunAsync();
    }

    public override async Task InitAsync()
    {   // Plugin entry point - fetch configuration values here by calling `GetArgumnet`
        await CreateHostedService();
    }
}

// Inject `BlamClient` singleton using dependency injection
internal class ExamplePluginService(BlamClient client) : PluginService
{
    private ExampleState _runState;
    private WorkflowBlueprintViewModel _blueprint;

    // ONSTART PHASE - called when the hosted service first starts on `host.RunAsync()`
    protected override async Task OnStartAsync(CancellationToken cancellationToken)
    {
        _runState = GetRunState<ExampleState>();                        // Initialise or retrieve the current saved run state

        var blueprintId = GetArgument<int>("blueprint_id");             // Fetch BLidget configuration value
        _blueprint = await client.GetWorkflowBlueprint(blueprintId);    // Fetch argument resource

        ProcessWork(cancellationToken);                                 // Begin work
    }

    // ONSTOP PHASE - called when the host application is stopped e.g. SIGTERM received
    protected override Task OnStopAsync(CancellationToken cancellationToken)
    {
        // Clean up steps ...

        return Task.CompletedTask;
    }

    private void ProcessWork(CancellationToken cancellationToken) =>
        Task.Run(async () => await ProcessWorkAsync(cancellationToken), cancellationToken);

    private async Task ProcessWorkAsync(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            // Do work ...

            // Save run state during plugin execution
            Save(_runState);

            // Log Debug
            LogDebug("Saved run state.");
        }
    }
}

internal class ExampleState
{
    public List<TrackedItem> Items { get; set; }
}

internal class TrackedItem
{
    public Guid Uuid { get; set; }
}

Web Server Pattern

// ExamplePlugin implements base class `PluginInitialiser`
internal class ExamplePlugin : PluginInitialiser
{
    private async Task CreateWebApp(string baseRoute, int port)
    {
        baseRoute = string.IsNullOrWhiteSpace(baseRoute) ? null : $"/{baseRoute}";

        var builder = WebApplication.CreateBuilder();

        // Configure serivces using dependency injection
        builder.Services.AddSingleton<ExamplePluginService>();
        builder.Services.AddHostedService(p => p.GetService<ExamplePluginService>());
        builder.Logging.ClearProviders();

        var app = builder.Build();

        // Define API endpoints using .Net minimal API
        app.MapGet($"{baseRoute}/hello", () =>
        {
            return "hello, world";
        });

        // Start web server and listen on incoming port
        await app.RunAsync($"http://*:{port}");
    }

    public override async Task InitAsync()
    {   // Plugin entry point - fetch configuration values here by calling `GetArgumnet`
        var baseRoute = GetArgument<string>("base_route");
        var port = GetArgument<int>("port");
        await CreateWebApp(baseRoute.Trim('/'), port);
    }
}

Next steps

To learn more about Blue Lucy, visit the Blue Lucy website.

Samples

  • Samples: Samples in this repository serve as a reference for developing BLigdets and Plugins
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.1.5.8 351 4/3/2024
3.1.4.9 471 2/6/2024
3.1.4.8 90 2/5/2024
3.1.3.19 141 2/5/2024
3.1.3.16 1,278 10/4/2023
3.1.0.25 296 8/14/2023
3.1.0.24 296 7/25/2023
3.1.0.23 180 7/17/2023
3.1.0.19 413 6/20/2023
3.1.0.18 185 6/8/2023
3.0.8.16 307 3/15/2023
3.0.8.11 317 2/7/2023
3.0.8.10 326 2/1/2023
3.0.7.16 427 11/29/2022
3.0.7.13 1,048 11/9/2022
3.0.6.62 467 10/4/2022
3.0.6.60 759 7/25/2022
3.0.6.59 487 7/15/2022
3.0.6.57 548 7/7/2022
3.0.6.49 552 6/15/2022
3.0.6.44 1,938 5/18/2022
3.0.6.42 517 5/11/2022
3.0.6.34 704 4/19/2022
3.0.6.33 566 4/7/2022
3.0.6.23 542 3/15/2022
3.0.6.21 513 3/7/2022
3.0.6.20 498 2/28/2022
3.0.6.14 536 1/16/2022
3.0.6.10 1,794 12/23/2021
3.0.6.8 359 12/15/2021
3.0.6.6 372 12/10/2021
3.0.6.5 522 12/9/2021
3.0.6.4 358 12/2/2021
3.0.6.2 3,047 11/25/2021
3.0.6 394 11/17/2021
3.0.5.46 404 11/10/2021
3.0.5.45 388 11/8/2021
3.0.5.42 395 10/26/2021
3.0.5.41 422 10/19/2021
3.0.5.36 468 9/15/2021
3.0.5.35 457 9/9/2021
3.0.5.34 432 8/31/2021
3.0.5.33 420 8/26/2021
3.0.5.32 396 8/20/2021
3.0.5.31 400 8/20/2021
3.0.5.30 413 8/19/2021
3.0.5.29 410 8/18/2021
3.0.5.28 406 8/18/2021
3.0.5.27 410 8/18/2021
3.0.5.26 409 8/16/2021
3.0.5.25 397 8/13/2021
3.0.5.24 407 8/12/2021
3.0.5.23 551 7/23/2021
3.0.5.22 385 7/21/2021
3.0.5.21 441 7/16/2021
3.0.5.20 455 7/16/2021
3.0.5.19 442 7/6/2021
3.0.5.18 515 6/24/2021
3.0.5.17 527 6/12/2021
3.0.5.16 462 6/3/2021
3.0.5.15 458 6/1/2021
3.0.5.14 444 5/20/2021
3.0.5.13 436 5/13/2021
3.0.5.12 417 5/10/2021
3.0.5.10 452 4/27/2021
3.0.5.8 452 4/21/2021
3.0.5.7 433 4/20/2021
3.0.5.5 459 4/9/2021
3.0.5.4 446 4/8/2021
3.0.5.3 404 4/1/2021
3.0.5.2 413 3/31/2021
3.0.5.1 417 3/31/2021
3.0.5 454 3/26/2021
3.0.4.14 473 3/24/2021
3.0.4.13 450 3/10/2021
3.0.4.12 445 3/8/2021
3.0.4.11 440 3/5/2021
3.0.4.10 418 3/4/2021
3.0.4.9 440 3/3/2021
3.0.4.8 463 3/2/2021
3.0.4.7 496 2/26/2021
3.0.4.6 485 2/24/2021
3.0.4.5 488 2/17/2021
3.0.4.4 477 2/11/2021
3.0.4.3 477 2/11/2021
3.0.4.2 477 2/9/2021
3.0.4.1 454 2/3/2021
3.0.4 481 2/2/2021
3.0.3.9 523 1/26/2021
3.0.3.8 470 1/26/2021
3.0.3.7 481 1/20/2021
3.0.3.6 471 1/18/2021
3.0.3.5 527 1/14/2021
3.0.3.4 493 1/12/2021
3.0.3.3 464 1/11/2021
3.0.3.2 469 1/10/2021
3.0.3 499 1/5/2021
3.0.2.9 504 12/23/2020
3.0.2.8 506 12/22/2020
3.0.2.7 543 12/10/2020
3.0.2.6 532 12/9/2020
3.0.2.5 504 12/8/2020
3.0.2.4 567 11/20/2020
3.0.2.3 527 11/19/2020
3.0.2.2 538 11/19/2020
3.0.2.1 569 11/18/2020
3.0.2 546 11/17/2020
3.0.1.49 542 11/11/2020
3.0.1.48 527 11/9/2020
3.0.1.47 537 10/27/2020
3.0.1.46 696 10/13/2020
3.0.1.45 543 10/12/2020
3.0.1.44 520 10/12/2020
3.0.1.43 552 10/8/2020
3.0.1.42 516 10/6/2020
3.0.1.41 530 10/5/2020
3.0.1.40 541 10/2/2020
3.0.1.39 523 10/1/2020
3.0.1.38 542 9/30/2020
3.0.1.37 528 9/30/2020
3.0.1.35 588 9/28/2020
3.0.1.34 570 9/11/2020
3.0.1.33 596 9/3/2020
3.0.1.32 560 9/1/2020
3.0.1.31 548 8/26/2020
3.0.1.30 554 8/25/2020
3.0.1.29 559 8/21/2020
3.0.1.28 538 8/18/2020
3.0.1.27 546 8/18/2020
3.0.1.26 534 8/17/2020
3.0.1.25 515 8/14/2020
3.0.1.24 522 8/10/2020
3.0.1.23 598 8/6/2020
3.0.1.22 624 7/29/2020
3.0.1.21 599 7/29/2020
3.0.1.20 555 7/29/2020
3.0.1.19 640 7/16/2020
3.0.1.18 562 7/15/2020
3.0.1.17 570 7/13/2020
3.0.1.16 621 7/10/2020
3.0.1.15 534 7/10/2020
3.0.1.14 593 7/8/2020
3.0.1.13 533 7/7/2020
3.0.1.12 633 7/2/2020
3.0.1.11 535 7/2/2020
3.0.1.10 553 7/2/2020
3.0.1.9 512 7/1/2020
3.0.1.8 509 7/1/2020
3.0.1.7 563 6/30/2020
3.0.1.6 542 6/30/2020
3.0.1.5 549 6/23/2020
3.0.1.4 605 6/22/2020
3.0.1.3 611 6/15/2020
3.0.1.2 649 6/14/2020
3.0.0.1 628 6/12/2020
3.0.0 616 6/10/2020
0.4.34 551 6/5/2020
0.4.33 652 6/4/2020
0.4.32 597 6/3/2020
0.4.31 599 6/2/2020
0.4.30 660 5/29/2020
0.4.29 589 5/20/2020
0.4.28 575 5/19/2020
0.4.27 604 5/5/2020
0.4.26 659 5/3/2020
0.4.25 602 5/1/2020
0.4.24 591 4/27/2020
0.4.23 598 4/23/2020
0.4.22 550 4/20/2020
0.4.21 559 4/20/2020
0.4.20 602 4/13/2020
0.4.19 734 4/3/2020
0.4.18 604 3/30/2020
0.4.16 728 3/28/2020
0.4.15 606 3/26/2020
0.4.14 685 3/25/2020
0.4.13 585 3/20/2020
0.4.12 582 3/19/2020
0.4.11 615 3/17/2020
0.4.10 593 3/10/2020
0.4.8 587 3/6/2020
0.4.7 563 3/6/2020
0.4.6 561 3/6/2020
0.4.5 611 3/5/2020
0.4.4 620 3/4/2020
0.4.3 596 2/27/2020
0.4.2 561 2/26/2020
0.4.1 616 2/18/2020
0.4.0 715 2/17/2020
0.0.3.24 626 2/17/2020
0.0.3.23 564 2/13/2020
0.0.3.22 620 2/10/2020
0.0.3.21 704 2/8/2020
0.0.3.20 713 1/30/2020
0.0.3.18 617 1/27/2020
0.0.3.17 652 1/17/2020
0.0.3.16 586 1/17/2020
0.0.3.15 576 1/17/2020
0.0.3.14 726 1/9/2020
0.0.3.13 650 1/8/2020
0.0.3.12 659 1/7/2020
0.0.3.11 625 1/6/2020
0.0.3.10 713 1/3/2020
0.0.3.9 684 1/2/2020
0.0.3.8 699 12/31/2019
0.0.3.7 654 12/20/2019
0.0.3.6 855 12/18/2019
0.0.3.5 656 12/17/2019
0.0.3.4 682 12/16/2019
0.0.3.3 699 12/2/2019
0.0.3.2 612 11/20/2019
0.0.3.1 664 11/18/2019
0.0.3 635 11/7/2019
0.0.2.9 666 11/1/2019
0.0.2.8 645 10/30/2019
0.0.2.7 756 10/26/2019
0.0.2.6 763 10/24/2019
0.0.2.5 645 10/22/2019
0.0.2.4 1,410 10/11/2019
0.0.2.3 646 10/11/2019
0.0.2.2 683 10/1/2019
0.0.2.1 659 9/26/2019
0.0.2 676 9/26/2019