better error handling in video decoding
This commit is contained in:
parent
e8c8455f43
commit
a672b0c78a
2 changed files with 50 additions and 10 deletions
|
@ -106,11 +106,16 @@ export class BaseMediaTile extends MessageTile {
|
|||
|
||||
get error() {
|
||||
if (this._error) {
|
||||
return `Could not decrypt media: ${this._error.message}`;
|
||||
return `Could not load media: ${this._error.message}`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
setViewError(err) {
|
||||
this._error = err;
|
||||
this.emitChange("error");
|
||||
}
|
||||
|
||||
async _loadEncryptedFile(file) {
|
||||
const blob = await this._mediaRepository.downloadEncryptedFile(file, true);
|
||||
if (this.isDisposed) {
|
||||
|
|
|
@ -15,10 +15,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import {BaseMediaView} from "./BaseMediaView.js";
|
||||
import {domEventAsPromise} from "../../../../dom/utils.js";
|
||||
|
||||
export class VideoView extends BaseMediaView {
|
||||
renderMedia(t, vm) {
|
||||
return t.video({
|
||||
renderMedia(t) {
|
||||
const video = t.video({
|
||||
// provide empty data url if video is not decrypted yet.
|
||||
// Chrome/Electron need this to enable the play button.
|
||||
src: vm => vm.videoUrl || `data:${vm.mimeType},`,
|
||||
|
@ -26,13 +27,47 @@ export class VideoView extends BaseMediaView {
|
|||
controls: true,
|
||||
preload: "none",
|
||||
poster: vm => vm.thumbnailUrl,
|
||||
onPlay: async evt => {
|
||||
if (!vm.videoUrl) {
|
||||
await vm.loadVideo();
|
||||
evt.target.play();
|
||||
}
|
||||
},
|
||||
style: `max-width: ${vm.width}px; max-height: ${vm.height}px;`
|
||||
onPlay: this._onPlay.bind(this),
|
||||
style: vm => `max-width: ${vm.width}px; max-height: ${vm.height}px;${vm.isPending ? "z-index: -1": ""}`
|
||||
});
|
||||
|
||||
video.addEventListener("error", this._onError.bind(this));
|
||||
|
||||
return video;
|
||||
}
|
||||
|
||||
async _onPlay(evt) {
|
||||
const vm = this.value;
|
||||
// download and decrypt the video if needed,
|
||||
if (!vm.videoUrl) {
|
||||
try {
|
||||
const video = evt.target;
|
||||
// this will trigger the src to update
|
||||
await vm.loadVideo();
|
||||
// important to only listen for this after src has changed,
|
||||
// or we get the error for the placeholder data url
|
||||
const loadPromise = domEventAsPromise(video, "loadeddata");
|
||||
// now, reload the video and play
|
||||
video.load();
|
||||
await loadPromise;
|
||||
video.play();
|
||||
} catch (err) {/* errors are already caught in error event handler */}
|
||||
}
|
||||
}
|
||||
|
||||
_onError(evt) {
|
||||
const vm = this.value;
|
||||
const video = evt.target;
|
||||
const err = video.error;
|
||||
if (err instanceof window.MediaError && err.code === 4) {
|
||||
if (!video.src.startsWith("data:")) {
|
||||
vm.setViewError(new Error(`this browser does not support videos of type ${vm.mimeType}.`));
|
||||
} else {
|
||||
// ignore placeholder url failing to load
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
vm.setViewError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue