流式 RTSP(AspNet 5 API、FFMPEG、Angular 10、videoJs)[已解决]

Posted

技术标签:

【中文标题】流式 RTSP(AspNet 5 API、FFMPEG、Angular 10、videoJs)[已解决]【英文标题】:Streaming RTSP (AspNet 5 API, FFMPEG, Angular 10, videoJs) 【发布时间】:2022-01-23 01:38:51 【问题描述】:

说明

我有一个通过 RTSP 连接到 IP 摄像机的 API (ASP.Net 5)。摄像头发送一个用 ffmpeg 转换的 h264 流作为 m3u8 流返回给 Angular 客户端,如下所示:

public async Task<ActionResult> GetCameraH264Stream()

        string deviceIp = "rtsp://[CAMERA_IP]/";
        string recordingUri = "rtsp://[USER:PASSWORD]@[CAMERA_IP]/axis-media/media.amp";
        
        string output = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".m3u8");
        var mediaInfo = await FFmpeg.GetMediaInfo(recordingUri);

        var conversionResult = FFmpeg.Conversions.New()
            .AddStream(mediaInfo.Streams)
            .SetOutput(output)
            .Start();
        
        // Allow any Cors
        Response.Headers.Add("Access-Control-Allow-Origin", "*");
        Response.Headers.Add("Cache-Control", "no-cache");
        
        // Open the file, and read the stream to return to the client
        FileStreamResult result = new FileStreamResult(System.IO.File.Open(output, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream");
        result.EnableRangeProcessing = true;
        return result;

如果我直接调用这个方法,浏览器会下载一个文件,我可以用 VLC 读取。

在我的 Angular 应用中,我有这个组件:

app-vjs-player

@Component(
       selector: 'app-vjs-player',
       template: '<video #target class="video-js" controls muted playsinline preload="none"> 
                  </video>',
       encapsulation: ViewEncapsulation.None,
    )
export class VjsPlayerComponent implements OnInit, OnDestroy 
  @ViewChild('target', static: true) target: ElementRef;
  
  @Input() options: 
      fluid: boolean,
      aspectRatio: string,
      autoplay: boolean,
      sources: 
          src: string,
          type: string,
      [],
      vhs: 
        overrideNative: true
      ,
  ;
  player: videojs.Player;

  constructor(
    private elementRef: ElementRef,
  )  

  ngOnInit() 
    // instantiate Video.js
    this.player = videojs(this.target.nativeElement, this.options, function onPlayerReady() 
      console.log('onPlayerReady', this);
    );
    
  

  ngOnDestroy() 
    // destroy player
    if (this.player) 
      this.player.dispose();
    
  


这个组件是这样使用的:

TS

playerOptions = 
    fluid: false,
    aspectRatio: "16:9",
      autoplay: false,
      sources: [
          src: 'https://localhost:44311/api/GetCameraH264Stream',
          type: 'application/x-mpegURL',
      ],

HTML

<app-vjs-player #videoJs [options]="playerOptions"></app-vjs-player>

问题

这一切似乎都很好,直到 vjs 在 api 返回流时抛出此错误:

错误:(CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) 无法加载媒体,可能是因为服务器或网络出现故障或格式不受支持

当我打开网络开发工具时,请求状态是“已取消”,但我不知道videojs是否因为无法读取filestreal而取消它,或者是因为API返回的方式流。

有什么想法吗?

来源

Forwarding RTSP stream from IP Camera to Browser in ASP.NET Core

VideoJs Angular integration

Xabe.FFMPEG

编辑

我试图限制分辨率和比特率,但我不能这样配置相机,有其他应用程序在使用它。相机没有任何允许此配置的流式传输 url 在更改 api 响应的内容类型后,我已经能够从我的代码中获取图像。我改变了:
FileStreamResult result = new FileStreamResult(System.IO.File.Open(output, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream");

FileStreamResult result = new FileStreamResult(System.IO.File.Open(output, FileMode.Open, FileAccess.Read, FileShare.Read), "application/x-mpegURL");

这样会显示第一个数据包,但仍会取消下一个请求。

【问题讨论】:

可能是服务器或者网络故障,或者格式不支持。这篇文章和你的情况差不多,希望对你有所帮助:github.com/videojs/video.js/issues/4751 嗨,你链接的 github 问题是关于 android/tablet 不兼容,这不是我的问题。但是有这样的评论:“我也猜想原因是元数据错误。就像你说的:高比特率,每秒帧数太多。”。我会尝试限制这一点并编辑结果 您的浏览器有问题吗? 我在企业网络下,所以只能用chrome和edge。我两个都有同样的问题 【参考方案1】:

响应 ContentType 的更改正在起作用(请参阅问题的最后编辑)。

取消的请求似乎是由于网络缓慢。上面的所有代码都按原样工作,除了最后一个 modif ( application/octet-stream => application/x-mpegURL )。这是更新的api方法:


public async Task<ActionResult> GetCameraH264Stream()

        string deviceIp = "rtsp://[CAMERA_IP]/";
        string recordingUri = "rtsp://[USER:PASSWORD]@[CAMERA_IP]/axis-media/media.amp";
        
        string output = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".m3u8");
        var mediaInfo = await FFmpeg.GetMediaInfo(recordingUri);

        var conversionResult = FFmpeg.Conversions.New()
            .AddStream(mediaInfo.Streams)
            .SetOutput(output)
            .Start();
        
        // Allow any Cors
        Response.Headers.Add("Access-Control-Allow-Origin", "*");
        Response.Headers.Add("Cache-Control", "no-cache");
        
        // Open the file, and read the stream to return to the client
        FileStreamResult result = new FileStreamResult(System.IO.File.Open(output, FileMode.Open, FileAccess.Read, FileShare.Read), "application/x-mpegURL");
        result.EnableRangeProcessing = true;
        return result;


【讨论】:

以上是关于流式 RTSP(AspNet 5 API、FFMPEG、Angular 10、videoJs)[已解决]的主要内容,如果未能解决你的问题,请参考以下文章

使用节点 js 的 RTSP 流式传输?

从 FFmpeg 流式传输 RTSP 需要哪些步骤?

通过 RTSP 流式传输 opencv 视频

ffmpeg 将 rtsp 重新流式传输到 mjpeg

是否可以在 iPhone 上流式传输 mms、ASX、RTSP 流?

如何使用 nodejs 服务器流式传输 RTSP?