diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts
index a76a01e3b4..9711e2f6da 100644
--- a/src/compile/nodes/Element.ts
+++ b/src/compile/nodes/Element.ts
@@ -534,7 +534,8 @@ export default class Element extends Node {
name === 'buffered' ||
name === 'seekable' ||
name === 'played' ||
- name === 'volume'
+ name === 'volume' ||
+ name === 'playbackRate'
) {
if (this.name !== 'audio' && this.name !== 'video') {
component.error(binding, {
diff --git a/src/compile/render-dom/wrappers/Element/Attribute.ts b/src/compile/render-dom/wrappers/Element/Attribute.ts
index c0c8327bb0..207e706fa4 100644
--- a/src/compile/render-dom/wrappers/Element/Attribute.ts
+++ b/src/compile/render-dom/wrappers/Element/Attribute.ts
@@ -445,6 +445,7 @@ const attribute_lookup = {
],
},
volume: { applies_to: ['audio', 'video'] },
+ playbackRate: { applies_to: ['audio', 'video'] },
width: {
applies_to: ['canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video'],
},
diff --git a/src/compile/render-dom/wrappers/Element/Binding.ts b/src/compile/render-dom/wrappers/Element/Binding.ts
index f2bf82a826..828d664001 100644
--- a/src/compile/render-dom/wrappers/Element/Binding.ts
+++ b/src/compile/render-dom/wrappers/Element/Binding.ts
@@ -139,6 +139,7 @@ export default class BindingWrapper {
break;
case 'currentTime':
+ case 'playbackRate':
case 'volume':
update_conditions.push(`!isNaN(${this.snippet})`);
break;
diff --git a/src/compile/render-dom/wrappers/Element/index.ts b/src/compile/render-dom/wrappers/Element/index.ts
index fa025bacbe..80a8308b93 100644
--- a/src/compile/render-dom/wrappers/Element/index.ts
+++ b/src/compile/render-dom/wrappers/Element/index.ts
@@ -83,7 +83,14 @@ const events = [
filter: (node: Element, name: string) =>
node.is_media_node() &&
name === 'volume'
- }
+ },
+ {
+ event_names: ['ratechange'],
+ filter: (node: Element, name: string) =>
+ node.is_media_node() &&
+ name === 'playbackRate'
+ },
+
];
export default class ElementWrapper extends Wrapper {
diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js
index a2b64d7a49..00bee3234c 100644
--- a/test/js/samples/media-bindings/expected.js
+++ b/test/js/samples/media-bindings/expected.js
@@ -38,7 +38,8 @@ function create_fragment(ctx) {
listen(audio, "pause", ctx.audio_play_pause_handler),
listen(audio, "progress", ctx.audio_progress_handler),
listen(audio, "loadedmetadata", ctx.audio_loadedmetadata_handler),
- listen(audio, "volumechange", ctx.audio_volumechange_handler)
+ listen(audio, "volumechange", ctx.audio_volumechange_handler),
+ listen(audio, "ratechange", ctx.audio_ratechange_handler)
];
},
@@ -46,12 +47,15 @@ function create_fragment(ctx) {
insert(target, audio, anchor);
audio.volume = ctx.volume;
+
+ audio.playbackRate = ctx.playbackRate;
},
p(changed, ctx) {
if (!audio_updating && changed.currentTime && !isNaN(ctx.currentTime)) audio.currentTime = ctx.currentTime;
if (changed.paused && audio_is_paused !== (audio_is_paused = ctx.paused)) audio[audio_is_paused ? "pause" : "play"]();
if (changed.volume && !isNaN(ctx.volume)) audio.volume = ctx.volume;
+ if (changed.playbackRate && !isNaN(ctx.playbackRate)) audio.playbackRate = ctx.playbackRate;
audio_updating = false;
},
@@ -69,7 +73,7 @@ function create_fragment(ctx) {
}
function instance($$self, $$props, $$invalidate) {
- let { buffered, seekable, played, currentTime, duration, paused, volume } = $$props;
+ let { buffered, seekable, played, currentTime, duration, paused, volume, playbackRate } = $$props;
function audio_timeupdate_handler() {
played = time_ranges_to_array(this.played);
@@ -105,6 +109,11 @@ function instance($$self, $$props, $$invalidate) {
$$invalidate('volume', volume);
}
+ function audio_ratechange_handler() {
+ playbackRate = this.playbackRate;
+ $$invalidate('playbackRate', playbackRate);
+ }
+
$$self.$set = $$props => {
if ('buffered' in $$props) $$invalidate('buffered', buffered = $$props.buffered);
if ('seekable' in $$props) $$invalidate('seekable', seekable = $$props.seekable);
@@ -113,6 +122,7 @@ function instance($$self, $$props, $$invalidate) {
if ('duration' in $$props) $$invalidate('duration', duration = $$props.duration);
if ('paused' in $$props) $$invalidate('paused', paused = $$props.paused);
if ('volume' in $$props) $$invalidate('volume', volume = $$props.volume);
+ if ('playbackRate' in $$props) $$invalidate('playbackRate', playbackRate = $$props.playbackRate);
};
return {
@@ -123,19 +133,21 @@ function instance($$self, $$props, $$invalidate) {
duration,
paused,
volume,
+ playbackRate,
audio_timeupdate_handler,
audio_durationchange_handler,
audio_play_pause_handler,
audio_progress_handler,
audio_loadedmetadata_handler,
- audio_volumechange_handler
+ audio_volumechange_handler,
+ audio_ratechange_handler
};
}
class SvelteComponent extends SvelteComponent_1 {
constructor(options) {
super();
- init(this, options, instance, create_fragment, safe_not_equal, ["buffered", "seekable", "played", "currentTime", "duration", "paused", "volume"]);
+ init(this, options, instance, create_fragment, safe_not_equal, ["buffered", "seekable", "played", "currentTime", "duration", "paused", "volume", "playbackRate"]);
}
}
diff --git a/test/js/samples/media-bindings/input.svelte b/test/js/samples/media-bindings/input.svelte
index 169d5c9341..4b5793ba93 100644
--- a/test/js/samples/media-bindings/input.svelte
+++ b/test/js/samples/media-bindings/input.svelte
@@ -6,6 +6,7 @@
export let duration;
export let paused;
export let volume;
+ export let playbackRate;
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/test/runtime/samples/binding-audio-currenttime-duration-volume/_config.js b/test/runtime/samples/binding-audio-currenttime-duration-volume/_config.js
index 921969179f..0a6754a210 100644
--- a/test/runtime/samples/binding-audio-currenttime-duration-volume/_config.js
+++ b/test/runtime/samples/binding-audio-currenttime-duration-volume/_config.js
@@ -8,24 +8,29 @@ export default {
assert.equal(component.t, 0);
assert.equal(component.d, 0);
assert.equal(component.v, 0.5);
+ assert.equal(component.r, 1);
assert.equal(component.paused, true);
const audio = target.querySelector('audio');
const timeupdate = new window.Event('timeupdate');
const durationchange = new window.Event('durationchange');
const volumechange = new window.Event('volumechange');
+ const ratechange = new window.Event('ratechange');
audio.currentTime = 10;
audio.duration = 20;
audio.volume = 0.75;
+ audio.playbackRate = 2;
audio.dispatchEvent(timeupdate);
audio.dispatchEvent(durationchange);
audio.dispatchEvent(volumechange);
+ audio.dispatchEvent(ratechange);
audio.play();
assert.equal(component.t, 10);
assert.equal(component.d, 0); // not 20, because read-only. Not sure how to test this!
assert.equal(component.v, 0.75);
+ assert.equal(component.r, 2);
assert.equal(component.paused, true); // ditto...
}
};
diff --git a/test/runtime/samples/binding-audio-currenttime-duration-volume/main.svelte b/test/runtime/samples/binding-audio-currenttime-duration-volume/main.svelte
index 68bef624bc..69335182e8 100644
--- a/test/runtime/samples/binding-audio-currenttime-duration-volume/main.svelte
+++ b/test/runtime/samples/binding-audio-currenttime-duration-volume/main.svelte
@@ -3,7 +3,8 @@
export let d;
export let paused;
export let v;
+ export let r;
-
\ No newline at end of file