Skip to content

Playback rate change #127

Open
Open
@hochstibe

Description

@hochstibe

Description

The video source changes on user input. The user can also set a playback rate.
I have 2 issues:

  • If the playback rate changed and a new video is loaded, an ExpressionChangedAfterItHasBeenCheckedError and it is resetted to the default Value
    • ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'attr.aria-valuetext': '2'. Current value: '1'. Find more at https://angular.io/errors/NG0100
  • If the playback rate is set programmatically with this.api.playbackRate = 2;, the same Error occurs, but the rate changes to the given value.

The documentation states, that the Media Directive should have the attribute playbackRate, but it is not possible to set with this.api.getDefaultMedia().playbackRate = 2;. Maybe this is linked to the issue?

Demo: ngx-videogular-showroom adapted

 
import { Component } from "@angular/core";
import { Subscription } from 'rxjs';
import { VgApiService } from '@videogular/ngx-videogular/core';
 

export interface IMedia {
    title: string;
    src: string;
    type: string;
}


@Component({
    selector: "app-smart-playlist",
    template: `
        <div>
            <vg-player (onPlayerReady)="onPlayerReady($event)">
            <vg-buffering></vg-buffering>
        
            <vg-controls>
                <vg-play-pause></vg-play-pause>
                <vg-playback-button [playbackValues]="playbackValues"></vg-playback-button>
        
                <vg-time-display vgProperty="current" vgFormat="mm:ss"></vg-time-display>
        
                <vg-scrub-bar>
                    <vg-scrub-bar-current-time></vg-scrub-bar-current-time>
                    <vg-scrub-bar-buffering-time></vg-scrub-bar-buffering-time>
                </vg-scrub-bar>
        
                <vg-time-display vgProperty="total" vgFormat="mm:ss"></vg-time-display>
        
                <vg-mute></vg-mute>
                <vg-volume></vg-volume>
        
                <vg-fullscreen></vg-fullscreen>
            </vg-controls>
        
            <video #media
                [vgMedia]="media"
                [src]="currentItem.src"
                id="singleVideo"
                preload="auto"
                crossorigin>
            </video>
        </vg-player>

        <button (click)="setRate()">Set Rate = 2</button>
        
        <ul>
            <li *ngFor="let item of playlist; let $index = index"
                (click)="onClickPlaylistItem(item, $index)"
                [class.selected]="item === currentItem">
                {{ item.title }}
            </li>
        </ul>
    </div>
    `,
    styles: [
        `
        vg-player {
            height: 50%;
        }
        ul {
            list-style-type: none;
            margin: 0;
            padding: 0;
            font-family: sans-serif;
        }
        
        ul li {
            padding: 10px;
            cursor: pointer;
        }
        
        ul li.selected {
            background-color: #dddddd;
        }
        
        ul li:hover {
            background-color: #cce6ee;
        }
        `
    ]
})
export class SmartPlaylistComponent {
    
    public playbackValues: string[];

    playlist: Array<IMedia> = [
        {
            title: 'Pale Blue Dot',
            src: 'http://static.videogular.com/assets/videos/videogular.mp4',
            type: 'video/mp4',
        },
        {
            title: 'Big Buck Bunny',
            src:
                'http://static.videogular.com/assets/videos/big_buck_bunny_720p_h264.mov',
            type: 'video/mp4',
        },
        {
            title: 'Elephants Dream',
            src:
                'http://static.videogular.com/assets/videos/elephants-dream.mp4',
            type: 'video/mp4',
        },
    ];
    currentIndex = 0;
    currentItem: IMedia = this.playlist[this.currentIndex];
    api: VgApiService;

    
 
    constructor(
        ) {
            this.playbackValues = ['0.25', '0.5', '1.0', '1.5', '2.0'];
        }
 
    onPlayerReady(api: VgApiService) {
        this.api = api;

        this.api
            .getDefaultMedia()
            .subscriptions.loadedMetadata.subscribe(() => {
                this.playVideo.bind(this);
                console.info('Rate after video loaded', this.api.playbackRate);
            });

        this.api
            .getDefaultMedia()
            .subscriptions.ended.subscribe(this.nextVideo.bind(this));

        this.api
            .getDefaultMedia()
            .subscriptions.rateChange.subscribe(_ => {
                console.info('rate Changed', this.api.playbackRate);
            });
    }

    nextVideo() {
        let currentRate = this.api.playbackRate;
        console.info('Rate before video changed', currentRate);
        this.currentIndex++;

        if (this.currentIndex === this.playlist.length) {
            this.currentIndex = 0;
        }

        this.currentItem = this.playlist[this.currentIndex];
    }

    playVideo() {
        this.api.play();
    }

    onClickPlaylistItem(item: IMedia, index: number) {
        this.currentIndex = index;
        this.currentItem = item;
    }

    setRate() {
        this.api.playbackRate = 2;
    }
}

Expected Behavior

  • Playback rate should be the same, if the video changes
  • Playback rate change with the api should not trigger the error

Actual Behavior

  • Because of the ExpressionChangedError, the rate is reset to the default value
  • Error is raised when setting the rate programmatically

Steps to Reproduce

  • Change the rate
    • Next video -> Error and reset to default value
  • Change the rate with the button
    • Error, but change is applied

Attachments

Try to include screenshots for bugs or design assets for enhancements

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions