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
schemeispl1orps2, anddirectorySchemeispl1dorps3. On apl1bucket a key rotation takes effect within about a minute (wait a minute before handing out links signed with the new key), and turningcors.allowCredentialson is refused with422 validation_error. - .NET (
Plycdn.AspNetCore.Storageand.Video1.4.0):PlycdnLinkSignerandPlycdnVideoSignersignpl1andpl1din 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, theanalyticssection of buckets and libraries, andtagsonPOST /sign. A refused tag is a422 validation_errorwhosedetailsays 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_busyandanalytics_unavailable. - .NET (
Plycdn.AspNetCore.Storageand.Video1.3.0):PlycdnSignOptions.Tags,Bucket.Analytics,BucketPatch.Analytics,GetDeliveryAnalyticsSeriesAsync,GetDeliveryBreakdownAsync,GetDeliveryBreakdownCsvAsync,PreviewAnalyticsRuleAsync, and for browser-requested linksPlycdnOptions.TagsForandAcceptBrowserTags(off by default: tags a browser sends are ignored, so visitors cannot label their own links). - Angular and React (
@plycdn/angular,@plycdn/react1.3.0): an optionaltagson 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
- 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. ContentClient.refreshSourceandContentUploadComponent.renewSourceare 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.- 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"onplycdn-content-playback,plycdn-content-resultsorplycdn-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. ContentPlaybackComponent.refreshandContentPlaybackComponent.seekare 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, setresultorstartSecondsas before.ContentPlaybackComponent.constructoralso takes anNgZone(1.10.0). Angular supplies it; only a unit test that constructs the component itself needs to pass one.ContentLabelshas 26 new required keys (1.10.0), so code that types a complete translation asContentLabelsstops 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. APartial<ContentLabels>(what the components'labelsinput takes) is unaffected.
C#
ContentController.RefreshSource(id,ct)andContentController.Settings(ct)are gone (1.7.0), and with them the routesassets/{id}/refresh-sourceandsettings. Renew source access through the source-access callback, and read settings on your server withGetSettingsAsync.- 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 theAuthorization: ApiKeyheader; this matters only to code that calls the API directly.
React
ContentLabelshas 26 new required keys (1.10.0), so code that types a complete translation asContentLabelsstops 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. APartial<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,matchPointerandresultAtMoment, for an interface of your own. - New labels (1.10.0):
matchPrevious,matchNext,matchPosition,matchAnnounce, thepointer*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") andcaptionsShort("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 inDEFAULT_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):
UpdateSettingsAsyncwith aContentSettingsChangechanges only what you name;ClearSettingsAsyncreturns an organization to its parent's settings. - Transcripts from code (1.7.0):
GetTranscriptAsyncandCorrectTranscriptAsync. - Usage, quotas and statements:
GetUsageAsyncby month,GetUsageDailyAsync,GetUsageQuotasAsync,ListStatementsAsync,GetStatementAsyncandExportStatementCsvAsync. First and last months are prorated when you go live mid-month. - Errors you can act on:
PlycdnApiExceptioncarriesCodeandRetryAfter. - 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.ContentSearchQuerytakes aFilter(ContentSearchFilter),PrincipalsandGroup. - Duplicate-charge waivers and usage detail:
SourceReference.ContentSha256declares 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);ContentUsagealso carriesProration,PayAsYouGoand anOrganizationsbreakdown. ContentSearchOptions.MaxUploadBytes(default 20 GB) caps what the upload route accepts.
Fixed
- On-screen text setting for connectors, from C# (1.10.0).
ContentConnectorRequest.ExtractContentFromVideoFramesis 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).
RegisterAssetAsyncandImportAsyncnow leavelanguageandaudioTrackout of the request unless you give a value; before, an unset value was sent as null and refused with422.
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
Metadataon each. - Settings in part:
UpdateSettingsAsyncchanges only what you name;ClearSettingsAsyncreturns an organization to its parent's settings. - Transcripts from code:
GetTranscriptAsyncandCorrectTranscriptAsync. - Changed: renewing source access and reading settings are server actions only. Angular's
refreshSource()and the controller routesassets/{id}/refresh-sourceandsettingsare 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 withGetSettingsAsync. - 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:03on a recording,Page 4 · Page 11in a document,Slide 3in 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 carryterms; React exportsmarkSpansandmarkTermsfor 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,goToLineandgoToPassagelabels;{time},{page},{slide},{row},{sheet}and{line}are filled in wherever your translation puts them (goToPage: 'पृष्ठ {page} पर जाएँ'). - Result locations gain
slide,title,resource,elementandsourcein 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-searchand@plycdn/content-search-react. Only names changed: the registration call isAddPlycdnContentSearch, the Angular modulePlycdnContentSearchModule, components<plycdn-content-upload>,<plycdn-content-search>,<plycdn-content-results>and<plycdn-content-playback>, the configuration sectionPlycdn, the default customer route/api/plycdn-content/v1, the organization claimplycdn_organization_id, CSS variables--plycdn-*, and the default service addresshttps://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_errornow says which field was wrong indetail, for example that a storage host was given withhttps://or a path. - Spoken language is honoured. The
languageyou register a recording with (for examplehiorta) 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.
- Remove
Plycdn.AspNetCore(and.S3or.AzureBlobif you use them) and install the new packages:Plycdn.AspNetCore.Storage, andPlycdn.AspNetCore.Videoif you use video. - Replace
using Plycdn;withusing Plycdn.AspNetCore.Storage;(andusing Plycdn.AspNetCore.Video;,using Plycdn.AspNetCore.Storage.S3;orusing Plycdn.AspNetCore.Storage.AzureBlob;where you use them). - Replace
AddPlycdn(...)withAddPlycdnStorage(...), or withAddPlycdnVideo(...)if you use video. ThePlycdnconfiguration section and its settings are unchanged, and so is yourIPlycdnStorageAuthorizer. - Where you call library, video or webhook methods, inject
PlycdnVideoApiinstead ofPlycdnStorageApi; where you sign video links, injectPlycdnVideoSignerinstead ofPlycdnLinkSigner.
// 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.
- Install
plycdn-angular-1.4.0.tgz(the one tarball carries both entry points). - Replace
PlycdnModule.forRoot(...)withPlycdnStorageModule.forRoot(...)imported from@plycdn/angular/storageand, if you play video,PlycdnVideoModule.forRoot(...)from@plycdn/angular/video. - 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.
- Install
plycdn-react-1.4.0.tgz. - Change imports from
@plycdn/reactto@plycdn/react/storageor@plycdn/react/video. Both export the samePlycdnProvider, 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.