AngularJS中UI-Router状态切换后销毁hls.js流的方法
解决AngularJS切换UI-Router状态后视频流持续加载的问题
你遇到的问题本质是状态切换时未正确清理HLS流实例和视频资源,导致浏览器仍在后台维持流连接。下面是针对性的解决方案,结合你的现有代码修改:
核心思路
当UI-Router切换状态时,原视图的控制器会被销毁,但你之前的代码没有主动清理HLS实例和视频元素的资源,所以流请求会持续。我们需要:
- 保存HLS实例的引用,方便后续销毁
- 在控制器销毁时,调用HLS的销毁方法并重置视频元素
具体修改步骤
1. 保存HLS实例到控制器作用域
在你的控制器中,把局部的hls变量改为作用域变量,这样在销毁钩子中能访问到它:
// 控制器内初始化HLS实例的代码修改 if(Hls.isSupported()) { var video = document.getElementById('video'); // 把hls赋值给$scope,而非局部变量 $scope.hls = new Hls(); $scope.hls.loadSource(window.monitorsIdsStreamWin[0]); $scope.hls.attachMedia(video); }
2. 监听控制器销毁事件,清理资源
在控制器中添加$destroy事件监听,这是AngularJS控制器销毁时的标准钩子,在这里完成流的清理:
// 在控制器内添加这段代码 $scope.$on('$destroy', function() { // 销毁HLS实例,停止所有流请求和定时器 if ($scope.hls) { $scope.hls.destroy(); $scope.hls = null; // 释放引用,帮助垃圾回收 } // 重置视频元素,彻底断开连接 const video = document.getElementById('video'); if (video) { video.pause(); // 先暂停播放 video.src = ''; // 清空视频源,切断流连接 video.load(); // 强制加载空内容,释放浏览器资源 } });
完整修改后的控制器代码
angular.module('yourApp').controller('VideoStreamController', function($scope, $http, $rootScope, serviceBase) { // 保存HLS实例引用 $scope.hls = null; // 控制器销毁时清理资源 $scope.$on('$destroy', function() { if ($scope.hls) { $scope.hls.destroy(); $scope.hls = null; } const video = document.getElementById('video'); if (video) { video.pause(); video.src = ''; video.load(); } }); // 获取流地址并初始化视频 $http.get(serviceBase + "aaaaaa" + Id) .then(function(response) { $rootScope.monitorsIds = []; angular.forEach(response.data, function(key, value) { $rootScope.monitorsIds.push(key.monitor); }); if(Hls.isSupported()) { const video = document.getElementById('video'); $scope.hls = new Hls(); $scope.hls.loadSource(window.monitorsIdsStreamWin[0]); $scope.hls.attachMedia(video); } }); });
额外注意事项
- 确保你使用的HLS.js版本支持
destroy()方法(v0.14.0及以上版本都支持,若版本过低建议升级) - 尽量避免直接操作DOM(比如
getElementById),可以改用AngularJS的ng-model或指令绑定视频元素,让框架帮你管理DOM引用 - 如果你的控制器是全局的(不随状态销毁),可以改用UI-Router的
$stateChangeStart钩子,在状态切换前执行清理逻辑
内容的提问来源于stack exchange,提问作者Arter
相关产品推荐
相关产品推荐

