@pbvision/partner-sdk 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +37 -61
  2. package/package.json +1 -1
  3. package/src/index.js +35 -10
package/README.md CHANGED
@@ -220,25 +220,19 @@ Folders organize the videos in your partner account's library. To put a new
220
220
  video in a folder, pass the folder's ID as the `fid` [metadata](#video-metadata)
221
221
  field.
222
222
 
223
- `getOrCreateFolder()` returns the folder in your library with exactly the name
224
- you give (inside `parent`, if you pass one), creating it if there is none.
225
- Calling it again with the same name returns the same folder, as long as you
226
- haven't renamed or moved it since, so it is safe to retry. Use a unique name
227
- for each event, such as one that includes its date; otherwise two events with
228
- the same name would share one folder. Names are 1 to 200 characters, with no
229
- leading or trailing whitespace.
223
+ `getOrCreateFolder()` returns the folder with the name you give (inside
224
+ `parent`, if you pass one), creating it if needed, so it's safe to retry. Use a
225
+ unique name for each event, such as one that includes its date. Names are 1 to
226
+ 200 characters, with no leading or trailing whitespace.
230
227
 
231
228
  ```javascript
232
229
  // a folder at the top level of your library
233
- const { fid, created } = await pbv.getOrCreateFolder('Spring Open 2026-04-18');
230
+ const { fid, created } = await pbv.getOrCreateFolder('Spring Open 2026-04-18'); // created: true if new
234
231
 
235
232
  // a folder inside it
236
233
  const { fid: day1Fid } = await pbv.getOrCreateFolder('Day 1', { parent: fid });
237
234
  ```
238
235
 
239
- `created` is `true` if the call made the folder, or `false` if it already
240
- existed.
241
-
242
236
  `updateFolder()` renames a folder, moves it, or makes it public. Fields you
243
237
  leave out stay as they are:
244
238
 
@@ -249,11 +243,9 @@ await pbv.updateFolder(fid, { public: true }); // let anyone with it
249
243
  await pbv.updateFolder(day1Fid, { public: true }); // and include Day 1 when it's viewed
250
244
  ```
251
245
 
252
- Anyone with a public folder's link can view its videos, signed in to PB Vision
253
- or not. A folder inside it is only included if it is public too, so make each
254
- folder you want shared public (the folders PB Vision makes to hold the games of
255
- a multi-game video follow their parent). `getPublicFolderUrl()` gives you the
256
- link:
246
+ Anyone with a public folder's link can view its videos, signed in or not. A
247
+ folder inside it is included only if it's public too. `getPublicFolderUrl()`
248
+ gives you the link:
257
249
 
258
250
  ```javascript
259
251
  const folderUrl = pbv.getPublicFolderUrl(fid);
@@ -262,12 +254,11 @@ const folderUrl = pbv.getPublicFolderUrl(fid);
262
254
 
263
255
  ### Recording with the PB Vision app
264
256
 
265
- The PB Vision iOS and Android apps can record a game straight into your
266
- partner account. For each game, `makeRecordingLink()` makes a video with the
257
+ For each game, `makeRecordingLink()` makes a video with the
267
258
  [metadata](#video-metadata) you give it and returns a link. Opening the link on
268
259
  a phone takes the PB Vision app straight to its camera, and the recording
269
- uploads to that video. Anyone can record from the link, whether or not they
270
- are signed in to PB Vision.
260
+ uploads to that video in your partner account. Anyone can record from the link,
261
+ signed in to PB Vision or not.
271
262
 
272
263
  A typical event goes like this:
273
264
 
@@ -307,22 +298,14 @@ await pbv.updateFolder(fid, { public: true });
307
298
  const eventUrl = pbv.getPublicFolderUrl(fid);
308
299
  ```
309
300
 
310
- `makeRecordingLink()` returns the new video's `vid`, your `uid`, and the `url`
311
- to share. It takes the same metadata as the other methods except
312
- `gameStartEpoch`: the game's time comes from its recording, and a time given
313
- in advance would override it, so passing one throws an error. It also throws
314
- if the account paying for the video can't pay for it (`hasCredits` is
315
- `false`).
316
-
317
- **One link per game.** If several people may ask for the same game's link (for
318
- example, any player on the court can tap "Record"), pass a `nonce` that
319
- identifies the game, such as your own ID for it. Every call with the same nonce
320
- returns the same video and link, even calls made at the same moment, and the
321
- first call decides the video's metadata. Until the video is uploaded, each call
322
- checks that the account paying for it can still pay; a call that can't gets no
323
- video and throws, and a later call gets the same video once the account can pay.
324
- `makeVideoId()` takes a `nonce` too (it returns `hasCredits: false` instead of
325
- throwing).
301
+ `makeRecordingLink()` returns `{ vid, uid, url }`. It takes the same metadata
302
+ as the other methods except `gameStartEpoch` (the game's time comes from its
303
+ recording). It throws if the account paying for the video can't pay for it.
304
+
305
+ **One link per game.** If several people may ask for the same game's link,
306
+ pass a `nonce` that identifies the game, such as your own ID for it. Every call
307
+ with that nonce returns the same video and link, even at the same moment, and
308
+ the first call's metadata is used. `makeVideoId()` takes a `nonce` too.
326
309
 
327
310
  ```javascript
328
311
  const { url } = await pbv.makeRecordingLink({ nonce: `${eventId}-${gameId}`, fid, playersForTagging });
@@ -330,41 +313,34 @@ const { url } = await pbv.makeRecordingLink({ nonce: `${eventId}-${gameId}`, fid
330
313
 
331
314
  **Camera settings.** By default the link records at 1080p and 30 FPS, and the
332
315
  person recording can't change either. Ask for 4K with `resolution: '4k'` or
333
- 60 FPS with `fps: 60`, and let the person recording choose with
334
- `mayChangeResolution: true` and `mayChangeFPS: true`. A phone that can't record
335
- what the link asks for steps down to the best quality it supports. The link's
336
- settings apply regardless of the recorder's own PB Vision subscription, but 4K
337
- requires your partner account to have 4K enabled; otherwise PB Vision rejects
338
- the upload.
316
+ 60 FPS with `fps: 60`; with `mayChangeResolution: true` or `mayChangeFPS: true`
317
+ the person recording may choose lower settings. Phones step down to what they
318
+ support, and recorders don't need a PB Vision subscription. 4K requires your
319
+ partner account to have 4K enabled, since PB Vision doesn't analyze video above
320
+ 1080p without it. `getMyPartnerAccountInfo()` says whether yours does, and
321
+ without it `makeRecordingLink()` refuses `resolution: '4k'`.
339
322
 
340
323
  ```javascript
324
+ const { is4K } = await pbv.getMyPartnerAccountInfo();
341
325
  const { url } = await pbv.makeRecordingLink({
342
326
  fid,
343
- resolution: '4k', // '1080p' (default) or '4k'
327
+ resolution: is4K ? '4k' : '1080p', // '1080p' (default) or '4k'
344
328
  fps: 60, // 30 (default) or 60
345
329
  mayChangeResolution: true, // default false
346
330
  mayChangeFPS: false // default false
347
331
  });
348
332
  ```
349
333
 
350
- **One recording per link.** Only the first upload to a link's video counts, so
351
- make a new link for each game.
352
-
353
- **Opening the link.** The PB Vision app opens only when the phone itself opens
354
- the link: when someone taps it (in a text message or an email, for example) or
355
- scans it as a QR code with the camera, or when your own app hands it to the
356
- operating system (for example with `UIApplication.shared.open()` on iOS or an
357
- `ACTION_VIEW` intent on Android). Don't load the link inside a webview or an
358
- in-app browser, where the app may not open. On a phone without the PB Vision
359
- app, the link shows a page for installing it.
360
-
361
- **Testing.** With the test server (`useProdServer: false`), links start with
362
- `pbvision://record` instead of `https://pb.vision/record` and end with
363
- `env=test`. Any installed PB Vision app opens them, so test on a phone with a
364
- development build of the app. Current App Store and Google Play versions check
365
- the link before recording and say it needs the development build. Older
366
- versions would record the game and upload it to production, where the test
367
- video doesn't exist, so the recording would be lost.
334
+ **One recording per link.** Only the first upload to a link's video counts.
335
+
336
+ **Opening the link.** Let the phone open the link: a tap, a scanned QR code,
337
+ or your app handing it to the operating system (`UIApplication.shared.open()`
338
+ on iOS, an `ACTION_VIEW` intent on Android). Don't load it in a webview or an
339
+ in-app browser, where the PB Vision app may not open. Without the app, the link
340
+ shows a page for installing it.
341
+
342
+ **Testing.** Links from the test server (`useProdServer: false`) start with
343
+ `pbvision://record` and need a development build of the PB Vision app.
368
344
 
369
345
  ### Video Editors and Viewers
370
346
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pbvision/partner-sdk",
3
3
  "description": "SDK for interacting with the PB Vision pickleball AI engine.",
4
- "version": "0.1.16",
4
+ "version": "0.1.18",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "engines": {
package/src/index.js CHANGED
@@ -68,6 +68,26 @@ export class PBVision {
68
68
  this.isDev = config === ENVIRONMENTS.test
69
69
  }
70
70
 
71
+ /**
72
+ * @typedef {Object} PartnerAccountInfo
73
+ * @property {boolean} is4K whether your partner account may upload video
74
+ * above 1080p. Without 4K, PB Vision does not analyze such a video.
75
+ */
76
+
77
+ /**
78
+ * Tells you what your partner account may do, e.g. whether to offer 4K.
79
+ *
80
+ * @returns {PartnerAccountInfo}
81
+ */
82
+ async getMyPartnerAccountInfo () {
83
+ const resp = await this.__callAPI('about', {})
84
+ const { is4K } = JSON.parse(resp)
85
+ if (is4K) {
86
+ this.__is4K = true
87
+ }
88
+ return { is4K }
89
+ }
90
+
71
91
  /**
72
92
  * Tells PB Vision to make an HTTP POST request your URL after each of your
73
93
  * videos is done processing.
@@ -274,9 +294,10 @@ export class PBVision {
274
294
  * By default the app records at 1080p and 30 FPS, and the person recording
275
295
  * can't change either. A phone that can't record what the link asks for
276
296
  * steps down to the best quality it supports. The link's settings apply
277
- * regardless of the recorder's own PB Vision subscription, but 4K requires
278
- * your partner account to have 4K enabled; otherwise PB Vision rejects the
279
- * upload.
297
+ * regardless of the recorder's own PB Vision subscription. 4K requires your
298
+ * partner account to have 4K enabled (see getMyPartnerAccountInfo()), so
299
+ * without it this refuses a 4K link rather than make a video PB Vision
300
+ * won't analyze.
280
301
  *
281
302
  * Each link is for one recording: only the first upload to its video
282
303
  * counts, so make a new link for each game. If several people may ask for
@@ -288,17 +309,14 @@ export class PBVision {
288
309
  * inside a webview, so that the phone can open the PB Vision app.
289
310
  *
290
311
  * With the test server (`useProdServer: false`), the link starts with
291
- * `pbvision://record` and ends with `env=test`. Any installed PB Vision app
292
- * opens it, so test with a development build of the app. Current App Store
293
- * and Google Play versions check the link before recording and say it needs
294
- * the development build; older versions would record the game and upload it
295
- * to production, where the test video doesn't exist, so it would be lost.
312
+ * `pbvision://record` and needs a development build of the PB Vision app.
296
313
  *
297
314
  * @param {RecordingLinkOptions} [options]
298
315
  * @returns {RecordingLink}
299
316
  * @throws {Error} if gameStartEpoch is given, a camera setting is invalid,
300
- * or PB Vision doesn't make the video (e.g. because the account paying for
301
- * it can't pay for it)
317
+ * 4K is asked for and your partner account doesn't have 4K, or PB Vision
318
+ * doesn't make the video (e.g. because the account paying for it can't
319
+ * pay for it)
302
320
  */
303
321
  async makeRecordingLink ({
304
322
  resolution = '1080p', fps = 30, mayChangeResolution = false, mayChangeFPS = false,
@@ -312,6 +330,13 @@ export class PBVision {
312
330
  assert(typeof mayChangeResolution === 'boolean', 'mayChangeResolution must be a boolean')
313
331
  assert(typeof mayChangeFPS === 'boolean', 'mayChangeFPS must be a boolean')
314
332
 
333
+ // checked before making the video, so a 4K link that PB Vision wouldn't
334
+ // analyze never gets one; only a yes is remembered, so an account that
335
+ // gets 4K later can ask for it without a new PBVision
336
+ if (resolution === '4k' && !this.__is4K && !(await this.getMyPartnerAccountInfo()).is4K) {
337
+ throw new Error('your partner account does not have 4K enabled, so PB Vision would not analyze a 4K recording; ask for 1080p, or ask PB Vision to enable 4K')
338
+ }
339
+
315
340
  const { vid, uid, hasCredits } = await this.makeVideoId({
316
341
  fileExt: 'mp4', userEmails, name, desc, facility, court, fid, playersForTagging, nonce })
317
342
  if (hasCredits === false) {