You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular15中如何通过VgApiService动态更换ngx-videogular媒体源

解决方案:Angular 15 + ngx-videogular 动态切换视频源

问题根源分析

  1. 新版本 ngx-videogular 已移除 VgMedia 可实例化类与 removeMedia 方法,媒体对象由 vgMedia 指令自动绑定到 <video> 元素,无法手动创建/移除。
  2. 你之前的 <source> 循环写法错误:用 *ngFor 遍历所有视频,但每个 <source> 都绑定同一个 currentIndex 的源,导致生成多个重复的 <source> 标签,浏览器只会加载第一个,后续切换不会触发重新加载。

正确实现方案

方案1:单源动态切换(推荐)

适用于每个视频仅需一种格式的场景,直接绑定当前视频的源到单个 <source> 标签,配合 VgApiService 触发媒体刷新。

模板代码
<vg-player (onPlayerReady)="onPlayerReady($event)">
  <video #media [vgMedia]="media" preload="auto" autoplay crossorigin>
    <source [src]="currentVideo.src" [type]="currentVideo.type">
  </video>
</vg-player>

<!-- 示例切换按钮 -->
<button (click)="nextVideo()">下一个视频</button>
组件代码
import { Component } from '@angular/core';
import { VgApiService } from '@videogular/ngx-videogular/core';

@Component({
  selector: 'app-video-player',
  templateUrl: './video-player.component.html'
})
export class VideoPlayerComponent {
  // 播放列表数据
  videoList = [
    { src: 'assets/video1.mp4', type: 'video/mp4' },
    { src: 'assets/video2.mp4', type: 'video/mp4' }
  ];
  currentIndex = 0;
  currentVideo = this.videoList[0];
  private api!: VgApiService;

  onPlayerReady(api: VgApiService) {
    this.api = api;
    // 监听视频结束事件,自动切换下一个
    this.api.getDefaultMedia().subscriptions.ended.subscribe(() => {
      this.nextVideo();
    });
  }

  nextVideo() {
    // 更新当前视频索引与源
    this.currentIndex = (this.currentIndex + 1) % this.videoList.length;
    this.currentVideo = this.videoList[this.currentIndex];
    
    // 等待Angular更新DOM后,刷新媒体并播放
    setTimeout(() => {
      this.api.getDefaultMedia().load();
      this.api.play();
    }, 100);
  }
}

方案2:多源动态切换(兼容多格式)

适用于单个视频需要提供多种格式(如mp4/webm)的场景,动态更新 <source> 列表后刷新媒体。

模板代码
<vg-player (onPlayerReady)="onPlayerReady($event)">
  <video #media [vgMedia]="media" preload="auto" autoplay crossorigin>
    <source *ngFor="let source of currentVideoSources" [src]="source.src" [type]="source.type">
  </video>
</vg-player>
组件代码
// 其他部分同方案1,仅修改播放列表与切换逻辑
videoList = [
  {
    sources: [
      { src: 'assets/video1.mp4', type: 'video/mp4' },
      { src: 'assets/video1.webm', type: 'video/webm' }
    ]
  },
  {
    sources: [
      { src: 'assets/video2.mp4', type: 'video/mp4' },
      { src: 'assets/video2.webm', type: 'video/webm' }
    ]
  }
];
currentVideoSources = this.videoList[0].sources;

nextVideo() {
  this.currentIndex = (this.currentIndex + 1) % this.videoList.length;
  this.currentVideoSources = this.videoList[this.currentIndex].sources;
  
  // 先卸载旧媒体,再加载新源
  this.api.getDefaultMedia().unload();
  setTimeout(() => {
    this.api.getDefaultMedia().load();
    this.api.play();
  }, 100);
}

内容的提问来源于stack exchange,提问作者MichaelE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:46:08