Release notes

plycdn ships two product lines, each with its own version. Content Search (the packages @plycdn/content-search, @plycdn/content-search-react and Plycdn.ContentSearch.AspNetCore) moves in step with the service. Storage & video (Plycdn.AspNetCore.Storage, .Video, .Storage.S3, .Storage.AzureBlob, @plycdn/angular and @plycdn/react) has its own line, and its packages always move together. The guides on this site describe the current release of both; how to move between releases is on Upgrading, together with moving to plycdn.com.

1Added in Content Search 1.12.0 and Storage & video 1.4.0

No breaking change: nothing you call today changes, and you can move to these versions without editing code.

plycdn links. New private buckets and video libraries normally sign links with a key plycdn holds for the bucket (scheme pl1, and pl1d for a whole video). A plycdn link keeps working whatever changes on our side, so a link you have already handed out does not break because of how we deliver. Buckets made before keep their links (ps2, ps3); we can switch a bucket to plycdn links for you, and its earlier links keep working for a week after. A bucket that allows credentialed cross-origin requests keeps ps2: a plycdn link is answered with a redirect, which a browser will not carry credentials across.

  • Service: the signing profile's scheme is pl1 or ps2, and directoryScheme is pl1d or ps3. On a pl1 bucket a key rotation takes effect within about a minute (wait a minute before handing out links signed with the new key), and turning cors.allowCredentials on is refused with 422 validation_error.
  • .NET (Plycdn.AspNetCore.Storage and .Video 1.4.0): PlycdnLinkSigner and PlycdnVideoSigner sign pl1 and pl1d in your process. Earlier versions ask plycdn to sign them and keep working.
  • Angular and React (1.4.0): no change for you; links still come from your backend.
  • Dashboard: a bucket's Signing tab shows which kind of link it signs, and the rotate confirmation says how soon old links stop.
  • Guides: Signing links yourself now gives the exact bytes to sign, with worked examples (including a key with non-ASCII characters), for signing without our packages.

2Added in Content Search 1.11.0 and Storage & video 1.3.0

No breaking change: nothing you call today changes, and you can move to these versions without editing code.

Delivery analytics: see what is behind your traffic. Switch it on for a bucket or video library and plycdn counts requests, bytes, cache results and status classes by the hour, and by up to three breakdowns you define: a part of the path, a query parameter, a regular expression, or a tag your server signs into a link (PlycdnSignOptions.Tags, private buckets). Read it over time or as a monthly breakdown (JSON, or CSV for a large month), by value, bucket or organization (one row per sub-organization for an account that has them), and try a rule on recent traffic before saving it. Each breakdown keeps a ceiling of distinct values per day that you can raise or return to your plan's. It is on every plan and adds two statement lines, Requests analysed and Tracked values, at the prices on your price list.

  • Service: GET /analytics/delivery, GET /analytics/delivery/breakdown, POST /buckets/{bucketId}/analytics/preview, the analytics section of buckets and libraries, and tags on POST /sign. A refused tag is a 422 validation_error whose detail says why; until link tags are switched on for your account, a request with tags is refused with "Link tags are not available yet". New codes: too_many_rows, too_many_organizations, export_busy and analytics_unavailable.
  • .NET (Plycdn.AspNetCore.Storage and .Video 1.3.0): PlycdnSignOptions.Tags, Bucket.Analytics, BucketPatch.Analytics, GetDeliveryAnalyticsSeriesAsync, GetDeliveryBreakdownAsync, GetDeliveryBreakdownCsvAsync, PreviewAnalyticsRuleAsync, and for browser-requested links PlycdnOptions.TagsFor and AcceptBrowserTags (off by default: tags a browser sends are ignored, so visitors cannot label their own links).
  • Angular and React (@plycdn/angular, @plycdn/react 1.3.0): an optional tags on a sign request; your backend decides whether to use it.
  • Dashboard: the Analytics tab of every bucket and library (charts over time, rules with a preview, and the ceiling), and Delivery → Delivery breakdown (by value, bucket or organization, with CSV).

Read Delivery analytics and the API reference.

3Content Search 1.10.0

For a team moving from 1.6.0, the last version you received. The packages are @plycdn/content-search (Angular) 1.10.0, @plycdn/content-search-react 1.10.0 and Plycdn.ContentSearch.AspNetCore 1.10.0. Install all three together: they move in step with the service.

The first section says what to do and the second what is new. The Content Search bundle's RELEASE-NOTES.md additionally lists every public difference between the 1.6.0 and 1.10.0 packages, read from the packages themselves.

What to do when upgrading from 1.6.0

Moving to plycdn.com (all packages)

Your server now talks to the hosted API at https://api.plycdn.com/. That is the default of the 1.10.0 C# package, so the server-side change is to remove any Plycdn:ApiBaseUrl setting (environment variable Plycdn__ApiBaseUrl) that names the old host; set it only if your plycdn contact gives you another HTTPS address. The browser packages never call the API directly, so they need no address. The full guides are at https://plycdn.com/docs, the one place they are kept up to date.

Angular

  1. Install the new package (1.12.0): npm install ./plycdn-content-search-1.12.0.tgz. Video and audio playback is built in: installing the package brings in everything it needs automatically (if you use a private npm registry or mirror, make sure it can serve the package's own dependency). The preview plays your file as it is.
  2. ContentClient.refreshSource and ContentUploadComponent.renewSource are gone (1.7.0). Source access is renewed by your server through the source-access callback; the upload row's Check again asks again. Remove any call to either.
  3. The preview plays recordings with its own controls (1.10.0). If you styled or relied on the browser's controls inside plycdn-content-playback, set [nativeControls]="true" on plycdn-content-playback, plycdn-content-results or plycdn-content-search. While focus is inside the preview, [ / ] and Alt+← / Alt+→ now move between matches (Alt+arrows are normally the browser's Back and Forward); [matchNavigation]="false" gives them back.
  4. ContentPlaybackComponent.refresh and ContentPlaybackComponent.seek are gone (1.10.0). The player renews an expired source link itself and resumes at the same second. Remove any call to either; to open another place, set result or startSeconds as before.
  5. ContentPlaybackComponent.constructor also takes an NgZone (1.10.0). Angular supplies it; only a unit test that constructs the component itself needs to pass one.
  6. ContentLabels has 26 new required keys (1.10.0), so code that types a complete translation as ContentLabels stops compiling (TS2739, "missing the following properties"). Spread the defaults under your own strings, const labels: ContentLabels = { ...DEFAULT_LABELS, ...mine }, or add the keys: back10, captions, captionsOff, captionsShort, exitFullscreen, forward10, fullscreen, matchAnnounce, matchNext, matchPosition, matchPrevious, mute, pause, play, pointerLine, pointerPage, pointerRow, pointerSheetRow, pointerSlide, pointerTime, quality, qualityAuto, seek, speed, unmute, volume. A Partial<ContentLabels> (what the components' labels input takes) is unaffected.

C#

  1. ContentController.RefreshSource(id,ct) and ContentController.Settings(ct) are gone (1.7.0), and with them the routes assets/{id}/refresh-source and settings. Renew source access through the source-access callback, and read settings on your server with GetSettingsAsync.
  2. API keys travel in the header only. A key in the query string was deprecated in 1.7.0 and, since 1.9.0, the service refuses it, in the query string or in a request body, with 401 api_key_required. The package has always sent the Authorization: ApiKey header; this matters only to code that calls the API directly.

React

  1. ContentLabels has 26 new required keys (1.10.0), so code that types a complete translation as ContentLabels stops compiling (TS2739). Spread the defaults under your own strings, const labels: ContentLabels = { ...DEFAULT_LABELS, ...mine }, or add the keys: back10, captions, captionsOff, captionsShort, exitFullscreen, forward10, fullscreen, matchAnnounce, matchNext, matchPosition, matchPrevious, mute, pause, play, pointerLine, pointerPage, pointerRow, pointerSheetRow, pointerSlide, pointerTime, quality, qualityAuto, seek, speed, unmute, volume. A Partial<ContentLabels> is unaffected.

Nothing else to change: the rest of the package has only gained.

What is new since 1.6.0

Angular

  • Moving between a file's matches in the preview (1.10.0). Previous and Next under the video, audio or document, with "Match 2 of 9" between them; the keys ] / Alt+→ and [ / Alt+←; a polite announcement of each move; (matchChanged) with the result as at the new match, which the results list follows. [matchNavigation]="false" turns the row and the keys off.
  • The preview's own player (1.10.0): labelled controls, the plycdn player's keyboard map, and a tick on the seek bar for every match (ticks closer than 6 pixels merge and cycle). The same player engine as the plycdn video player, so expired links are renewed without interrupting the reader. [nativeControls]="true" keeps the browser's controls, with the ticks in a strip.
  • Match helpers (1.10.0): matchesInOrder, matchIndex, adjacentMatch, markerPositions, matchPointer and resultAtMoment, for an interface of your own.
  • New labels (1.10.0): matchPrevious, matchNext, matchPosition, matchAnnounce, the pointer* templates and the player controls' names. All have English defaults.
  • Theming (1.10.0): --pcs-marker, --pcs-marker-active, --pcs-player-bar, --pcs-player-text.
  • Two more label keys (1.10.0): qualityAuto ("Auto") and captionsShort ("CC"), the short names the player's quality and captions buttons show. Both packages have them, with English defaults.
  • PDF viewer (1.9.1): the PDF viewer inside the package now includes a security update. Nothing to change.

React

  • Match helpers and labels (1.10.0): matchesInOrder, matchIndex, adjacentMatch, markerPositions, matchPointer, and the same new labels in DEFAULT_LABELS. The API reference ("Match navigation in your own interface") shows Previous / Next and seek-bar markers in about twenty lines.

C#

  • Sub-organizations and the account audit from code (1.7.0): PlycdnAccountApi, with an admin key.
  • Settings in part (1.7.0): UpdateSettingsAsync with a ContentSettingsChange changes only what you name; ClearSettingsAsync returns an organization to its parent's settings.
  • Transcripts from code (1.7.0): GetTranscriptAsync and CorrectTranscriptAsync.
  • Usage, quotas and statements: GetUsageAsync by month, GetUsageDailyAsync, GetUsageQuotasAsync, ListStatementsAsync, GetStatementAsync and ExportStatementCsvAsync. First and last months are prorated when you go live mid-month.
  • Errors you can act on: PlycdnApiException carries Code and RetryAfter.
  • Everything the API offers, from C# (since 1.6.0): AnswerAsync, SuggestAsync, GetRelatedAsync, GetLibraryHealthAsync, GetSearchAnalyticsAsync, GetMetadataAsync, GetPermissionsAsync, collections (ListCollectionsAsync, UpsertCollectionAsync, DeleteCollectionAsync, SetCollectionMembersAsync), GetSynonymsAsync / SetSynonymsAsync, boosts and pins. ContentSearchQuery takes a Filter (ContentSearchFilter), Principals and Group.
  • Duplicate-charge waivers and usage detail: SourceReference.ContentSha256 declares the checksum of a large recording we read in ranges, so a copy of it is not charged twice (see "How usage is counted" in the Integration guide); ContentUsage also carries Proration, PayAsYouGo and an Organizations breakdown.
  • ContentSearchOptions.MaxUploadBytes (default 20 GB) caps what the upload route accepts.

Fixed

  • On-screen text setting for connectors, from C# (1.10.0). ContentConnectorRequest.ExtractContentFromVideoFrames is now sent when you create a connector and when you update one, and an update that leaves it unset keeps the value already stored (including one set in the dashboard). If you set it from C# earlier and saw no effect, set it again.
  • C#: registering a file and importing no longer fail when you leave the language unset (1.10.0). RegisterAssetAsync and ImportAsync now leave language and audioTrack out of the request unless you give a value; before, an unset value was sent as null and refused with 422.

Documented error codes

The API reference's error table documents more codes than it did in 1.6.0 (including the storage, video and webhook codes). None was removed, so no code you match on today has changed meaning. The bundle's RELEASE-NOTES.md lists every one added.

4Content Search 1.5.0 to 1.9.0

What each of these releases added, newest first. If you are moving from 1.6.0 or earlier, the 1.10.0 section above says what to change; this part says what you gained on the way. Everything here is additive unless it says Changed.

Version 1.7

  • Two keys at once, and admin keys. Up to two API keys can be active, so a key is replaced without downtime: rotate, deploy, then deactivate the old one. Keys are managed in the dashboard only - they are credentials, managed by people - and the key routes refuse every API key with dashboard_session_required. An admin key, created only in the dashboard, manages sub-organizations and reads the account audit from code (PlycdnAccountApi).
  • Sub-organizations from code, with your own Metadata on each.
  • Settings in part: UpdateSettingsAsync changes only what you name; ClearSettingsAsync returns an organization to its parent's settings.
  • Transcripts from code: GetTranscriptAsync and CorrectTranscriptAsync.
  • Changed: renewing source access and reading settings are server actions only. Angular's refreshSource() and the controller routes assets/{id}/refresh-source and settings are gone. The upload component's waiting row offers Check again, and access is renewed by your server through the source-access callback. Read settings on your server with GetSettingsAsync.
  • Changed: sub-organization and account-audit routes refuse a standard key (admin_key_required): use an admin key, or the dashboard. People, invitations and the organization profile routes (/api/users, /api/organizations) refuse every API key (dashboard_session_required): manage them in the dashboard.
  • Recorded: the account audit now also lists every dashboard "search as" (dashboard.search_as): who, which organization and how many principals, never their names.

Version 1.6

  • One result per file. A file that answers a query in several places is one result, listing every place it matched as a jump-to link - 02:14 · 07:51 · 12:03 on a recording, Page 4 · Page 11 in a document, Slide 3 in a course. The Angular <plycdn-content-search> does this by default ([groupByFile]="false" restores one result per passage). React: search(q, { group: 'file' }); .NET: new ContentSearchQuery { Group = "file" }. Paging then counts files. See "One result per file" in the API reference.
  • The words that matched are marked - in each result's snippet and, when a document opens in place, in the matched line, paragraph or row. PDFs now render in the component at the matched page with the passage highlighted and the words marked, with zoom and page controls; this needs the same storage CORS rule as Word and Excel, and falls back to the browser's viewer without it. A result found by meaning alone, sharing no words with the question, says so ("Matched by meaning"). Results carry highlights, pages carry terms; React exports markSpans and markTerms for your own interface.
  • SCORM packages of every common shape are read: launch pages that navigate between lesson pages, slide players whose course is in a data file, Articulate Rise exports, PDF and Word files inside a package, and packages zipped inside a folder. See "What can be indexed".
  • The result button says where it goes: "Play from 2:14" on a recording, "Go to page 4" in a PDF, "Go to slide 3" in a course, "Go to row 12" in a spreadsheet, "Go to line 40" in text, "Go to the passage" otherwise - instead of a generic "Preview video". Translate it with the playFrom, goToPage, goToSlide, goToRow, goToSheetRow, goToLine and goToPassage labels; {time}, {page}, {slide}, {row}, {sheet} and {line} are filled in wherever your translation puts them (goToPage: 'पृष्ठ {page} पर जाएँ').
  • Result locations gain slide, title, resource, element and source in every package's types, so a course result can read "Slide 4 · Definition and Scope".

Everything is additive: an integration built on 1.5 keeps working unchanged.

Version 1.5

  • New package names. The packages are now Plycdn.ContentSearch.AspNetCore, @plycdn/content-search and @plycdn/content-search-react. Only names changed: the registration call is AddPlycdnContentSearch, the Angular module PlycdnContentSearchModule, components <plycdn-content-upload>, <plycdn-content-search>, <plycdn-content-results> and <plycdn-content-playback>, the configuration section Plycdn, the default customer route /api/plycdn-content/v1, the organization claim plycdn_organization_id, CSS variables --plycdn-*, and the default service address https://api.plycdn.com/. If you are upgrading, rename these and update the callback URL registered in the dashboard to the new route.
  • A React package for search, answers, suggestions, related files, the library and progress. See "Using React".
  • Clearer validation errors. A validation_error now says which field was wrong in detail, for example that a storage host was given with https:// or a path.
  • Spoken language is honoured. The language you register a recording with (for example hi or ta) is passed to transcription, which improves accuracy for Indian languages.

5Storage & video 1.2.0

The storage and video packages are split by purpose. Before 1.2.0, Plycdn.AspNetCore held storage and video together, and @plycdn/angular and @plycdn/react each had one entry point for everything. From 1.2.0 you install and import only what you use: storage, video, or both. The names changed; what the packages do, the routes your frontend calls and everything plycdn answers did not. Nothing about the service, your data, your API key or your plan changes.

Most teams simply install the 1.2.0 names. If you installed a 1.1.x package, the table and the steps below take you across.

New names

Before (1.1.x) From 1.2.0
NuGet Plycdn.AspNetCore (storage and video) Plycdn.AspNetCore.Storage (buckets, uploads, delivery, domains, cache, signing, the browser controller) and Plycdn.AspNetCore.Video (libraries, playback, webhooks, the video route). Video depends on Storage
NuGet Plycdn.AspNetCore.S3 Plycdn.AspNetCore.Storage.S3
NuGet Plycdn.AspNetCore.AzureBlob Plycdn.AspNetCore.Storage.AzureBlob
Namespace Plycdn Plycdn.AspNetCore.Storage, Plycdn.AspNetCore.Video, Plycdn.AspNetCore.Storage.S3, Plycdn.AspNetCore.Storage.AzureBlob (the namespace matches the package)
services.AddPlycdn(...) services.AddPlycdnStorage(...), or services.AddPlycdnVideo(...), which registers storage as well
Library, video and webhook calls on PlycdnStorageApi (CreateLibraryAsync, CreateVideoAsync, CreateWebhookAsync and the rest) The same methods on PlycdnVideoApi, which AddPlycdnVideo registers and which is constructed from a PlycdnStorageApi
PlycdnLinkSigner.SignVideoAsync PlycdnVideoSigner.SignVideoAsync, with the same arguments
PlycdnWebhookVerifier, PlycdnWebhookEvent, PlycdnWebhookSignatureException, PlaybackLink, Library, Video The same names, in Plycdn.AspNetCore.Video
GET api/plycdn/v1/videos/{id} served by PlycdnStorageController The same route, now served by PlycdnVideoController (the sign route stays on PlycdnStorageController)
npm @plycdn/angular: everything from one entry point @plycdn/angular/storage (PlycdnStorageModule, PlycdnStorageClient, PlycdnUploadComponent, PlycdnFileBrowserComponent, PlycdnUploader) and @plycdn/angular/video (PlycdnVideoModule, PlycdnPlayerComponent, PlycdnPlaybackService, PlycdnPlayerCore). The root @plycdn/angular holds the shared types, failures, messages and theme, and the framework-free upload and player engines that the two entry points re-export
PlycdnModule.forRoot(...) PlycdnStorageModule.forRoot(...) for uploads and the file browser, PlycdnVideoModule.forRoot(...) for the player. PlycdnModule is removed
npm @plycdn/react: everything from the root @plycdn/react/storage (provider, upload, file browser, hooks, uploader, client) and @plycdn/react/video (provider, player, usePlayback, useVideo, PlycdnPlayerCore). The root holds types only

The packages are one version line again: 1.2.0 for all of them.

Regional hostnames use a short label

Storage hostnames carry the region's short host label, not its region code: s3.in-mum.plycdn.net, <bucket>.s3.in-mum.plycdn.net, blob.in-mum.plycdn.net, <account>.blob.in-mum.plycdn.net and, for upload parts, in-mum.upload.plycdn.com (Mumbai; later regions follow the same pattern, for example in-hyd and sg-sin). The region code does not change. mumbai is still what you pass to the API and the SDKs, what you set as the region in S3 tools, and what requests are signed with. The packages keep no list of regions or labels: region codes are data from GET /regions. Create clients with await PlycdnS3.CreateClientAsync(api, organizationId, "mumbai", ...) or await PlycdnBlob.CreateServiceClientAsync(api, organizationId, ...), which read the label from the region's endpoints. To skip the lookup, set HostLabel (PlycdnCompatOptions.HostLabel, or the hostLabel argument) from that same listing. The region code is never used as a host label: a client that cannot find the label fails with a message that says so, instead of connecting to a host that does not exist. If you register a client from configuration (AddPlycdnS3, AddPlycdnBlob) or call CreateClient / CreateServiceClient without the async lookup, set Plycdn:S3:HostLabel or Plycdn:Blob:HostLabel (the label in the region's S3 endpoint from GET /regions).

What to change

ASP.NET Core.

  1. Remove Plycdn.AspNetCore (and .S3 or .AzureBlob if you use them) and install the new packages: Plycdn.AspNetCore.Storage, and Plycdn.AspNetCore.Video if you use video.
  2. Replace using Plycdn; with using Plycdn.AspNetCore.Storage; (and using Plycdn.AspNetCore.Video;, using Plycdn.AspNetCore.Storage.S3; or using Plycdn.AspNetCore.Storage.AzureBlob; where you use them).
  3. Replace AddPlycdn(...) with AddPlycdnStorage(...), or with AddPlycdnVideo(...) if you use video. The Plycdn configuration section and its settings are unchanged, and so is your IPlycdnStorageAuthorizer.
  4. Where you call library, video or webhook methods, inject PlycdnVideoApi instead of PlycdnStorageApi; where you sign video links, inject PlycdnVideoSigner instead of PlycdnLinkSigner.
// Before (1.1.x)
builder.Services.AddPlycdn(builder.Configuration);
var link = await signer.SignVideoAsync(orgId, libraryId, videoId);        // PlycdnLinkSigner

// From 1.2.0
builder.Services.AddPlycdnVideo(builder.Configuration);
var link = await videoSigner.SignVideoAsync(orgId, libraryId, videoId);   // PlycdnVideoSigner

Angular.

  1. Install plycdn-angular-1.4.0.tgz (the one tarball carries both entry points).
  2. Replace PlycdnModule.forRoot(...) with PlycdnStorageModule.forRoot(...) imported from @plycdn/angular/storage and, if you play video, PlycdnVideoModule.forRoot(...) from @plycdn/angular/video.
  3. Change imports of services, components and the uploader to the entry point that now holds them (table above). Templates (<plycdn-upload>, <plycdn-file-browser>, <plycdn-player>) are unchanged.

React.

  1. Install plycdn-react-1.4.0.tgz.
  2. Change imports from @plycdn/react to @plycdn/react/storage or @plycdn/react/video. Both export the same PlycdnProvider, so one provider serves a page that uses both. Props and hooks are unchanged.

Player type names

The exported player types and values no longer name the playback technology. If your code imports the player's engine type or its loader types from @plycdn/angular/video or @plycdn/react/video, use the new names. Behaviour is unchanged.

Before Now
HlsLike AdaptiveStreamLike
HlsLevel AdaptiveStreamLevel
HlsConstructor AdaptiveStreamConstructor

The loader is now loadAdaptiveStream, and the player reports its engine as 'adaptive'.

What did not change

  • The wire contract: every route, field and error code, and what your frontend sends to your backend.
  • Behaviour of uploads, signed links, playback, webhooks and the S3 and Azure clients.
  • Your API key, buckets, libraries, domains, webhooks and plan.

The full guides for the new packages are Storage & video with ASP.NET Core, with Angular and with React.