Skip to content

Commit

Permalink
feat(offline): improve the speed of offline downloads (#4168)
Browse files Browse the repository at this point in the history
Add the possibility to configure the number of downloads in parallel per stream. If you put a higher value the download time can decrease.

Related to #4166

Co-authored-by: Joey Parrish <[email protected]>
  • Loading branch information
Álvaro Velad Galván and joeyparrish authored Apr 28, 2022
1 parent c5f474e commit 73f6de3
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 8 deletions.
1 change: 1 addition & 0 deletions demo/common/message_ids.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ shakaDemo.MessageIds = {
NUMBER_INTEGER_WARNING: 'DEMO_NUMBER_INTEGER_WARNING',
NUMBER_NONZERO_DECIMAL_WARNING: 'DEMO_NUMBER_NONZERO_DECIMAL_WARNING',
NUMBER_NONZERO_INTEGER_WARNING: 'DEMO_NUMBER_NONZERO_INTEGER_WARNING',
NUMBER_OF_PARALLEL_DOWNLOADS: 'DEMO_NUMBER_OF_PARALLEL_DOWNLOADS',
OFFLINE_SECTION_HEADER: 'DEMO_OFFLINE_SECTION_HEADER',
PREFER_FORCED_SUBS: 'DEMO_PREFER_FORCED_SUBS',
PREFER_NATIVE_HLS: 'DEMO_PREFER_NATIVE_HLS',
Expand Down
4 changes: 3 additions & 1 deletion demo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@ shakaDemo.Config = class {
const docLink = this.resolveExternLink_('.OfflineConfiguration');
this.addSection_(MessageIds.OFFLINE_SECTION_HEADER, docLink)
.addBoolInput_(MessageIds.USE_PERSISTENT_LICENSES,
'offline.usePersistentLicense');
'offline.usePersistentLicense')
.addNumberInput_(MessageIds.NUMBER_OF_PARALLEL_DOWNLOADS,
'offline.numberOfParallelDownloads');
}

/** @private */
Expand Down
1 change: 1 addition & 0 deletions demo/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
"DEMO_NUMBER_INTEGER_WARNING": "Must be a positive integer.",
"DEMO_NUMBER_NONZERO_DECIMAL_WARNING": "Must be a positive, nonzero number.",
"DEMO_NUMBER_NONZERO_INTEGER_WARNING": "Must be a positive, nonzero integer.",
"DEMO_NUMBER_OF_PARALLEL_DOWNLOADS": "Number of parallel downloads",
"DEMO_OBSERVE_QUALITY_CHANGES": "Observe media quality changes",
"DEMO_OFFLINE": "Downloadable",
"DEMO_OFFLINE_SEARCH": "Filters for assets that can be stored offline.",
Expand Down
4 changes: 4 additions & 0 deletions demo/locales/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,10 @@
"description": "A warning on number inputs, telling the user what the expected input format is.",
"message": "Must be a positive, nonzero integer."
},
"DEMO_NUMBER_OF_PARALLEL_DOWNLOADS": {
"description": "The name of a configuration value.",
"message": "Number of parallel downloads."
},
"DEMO_OBSERVE_QUALITY_CHANGES": {
"description": "The name of a configuration value.",
"message": "Observe media quality changes"
Expand Down
3 changes: 3 additions & 0 deletions demo/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,10 @@ shakaDemo.Main = class {
};
asset.storedProgress = 0;
this.dispatchEventWithName_('shaka-main-offline-progress');
const start = Date.now();
const stored = await storage.store(asset.manifestUri, metadata).promise;
const end = Date.now();
console.log('Download time:', end - start);
asset.storedContent = stored;
} catch (error) {
this.onError_(/** @type {!shaka.util.Error} */ (error));
Expand Down
8 changes: 7 additions & 1 deletion externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,8 @@ shaka.extern.CmcdConfiguration;
* function(shaka.extern.TrackList):!Promise<shaka.extern.TrackList>,
* downloadSizeCallback: function(number):!Promise<boolean>,
* progressCallback: function(shaka.extern.StoredContent,number),
* usePersistentLicense: boolean
* usePersistentLicense: boolean,
* numberOfParallelDownloads: number
* }}
*
* @property {function(shaka.extern.TrackList):!Promise<shaka.extern.TrackList>}
Expand All @@ -1098,6 +1099,11 @@ shaka.extern.CmcdConfiguration;
* license. A network will be required to retrieve a temporary license to
* view.
* Defaults to <code>true</code>.
* @property {number} numberOfParallelDownloads
* Number of parallel downloads.
* Note: normally browsers limit to 5 request in parallel, so putting a
* number higher than this will not help it download faster.
* Defaults to <code>5</code>.
* @exportDoc
*/
shaka.extern.OfflineConfiguration;
Expand Down
8 changes: 6 additions & 2 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,9 @@ shaka.offline.Storage = class {
const startTime =
manifest.presentationTimeline.getSegmentAvailabilityStart();

const numberOfParallelDownloads = config.offline.numberOfParallelDownloads;
let groupId = 0;

shaka.offline.Storage.forEachSegment_(stream, startTime, (segment) => {
const pendingSegmentRefId =
shaka.offline.DownloadInfo.idForSegmentRef(segment);
Expand All @@ -1337,7 +1340,7 @@ shaka.offline.Storage = class {
const segmentDownload = new shaka.offline.DownloadInfo(
segment,
estimateId,
stream.id,
groupId,
/* isInitSegment= */ false);
toDownload.set(pendingSegmentRefId, segmentDownload);
}
Expand All @@ -1352,7 +1355,7 @@ shaka.offline.Storage = class {
const initDownload = new shaka.offline.DownloadInfo(
segment.initSegmentReference,
estimateId,
stream.id,
groupId,
/* isInitSegment= */ true);
toDownload.set(pendingInitSegmentRefId, initDownload);
}
Expand All @@ -1372,6 +1375,7 @@ shaka.offline.Storage = class {
dataKey: 0,
};
streamDb.segments.push(segmentDB);
groupId = (groupId + 1) % numberOfParallelDownloads;
});

return streamDb;
Expand Down
2 changes: 2 additions & 0 deletions lib/util/player_configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ shaka.util.PlayerConfiguration = class {
// unexpected behaviours when someone tries to plays downloaded content
// without a persistent license.
usePersistentLicense: true,

numberOfParallelDownloads: 5,
};

const abr = {
Expand Down
5 changes: 1 addition & 4 deletions test/offline/storage_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1110,10 +1110,7 @@ filterDescribe('Storage', storageSupport, () => {
aRequestIsStarted.resolve();
await promise;

// All downloads for a given stream are in the same "download group",
// and will be downloaded sequentially. Thus, we expect only the first
// download to be aborted.
expect(abortCheck()).toBe(i == 0 ? true : false);
expect(abortCheck()).toBe(true);

return new ArrayBuffer(16);
});
Expand Down

0 comments on commit 73f6de3

Please sign in to comment.