我正在尝试从服务器获取视频以在前端播放。
目前,我正在开发一个用户Angular 4前端和Rails 5 API后端的项目。目标是将视频上传到后端以便在前端进行流式传输。但是,我遇到的问题是Firefox说视频内容类型错误。
HTTP “Content-Type” of “text/html” is not supported. Load of media resource http://localhost:4200/ failed. 1)
All candidate resources failed to load. Media load paused. 1)
Cannot play media. No decoders for requested formats: text/html
所以,我做了一些阅读和故障排除,并得出结论,问题必须在后端,所以我添加了一个mime类型到rails并明确添加了内容类型。这是相关的后端代码。
电影控制器 class MoviesController< ApplicationController的 def指数 @movies = Movie.all
render json: @movies, status: 200
end
def create
movie = Movie.new(movie_params)
if movie.save
render json: movie, status: 201
else
render json: { errors: movie.errors }, status: 422
end
end
def update
movie = Movie.find(params[:id])
if movie.update_attributes(movie_params)
render json: movie, status: 200
else
render json: { errors: movie.errors }, status: 422
end
end
def show
movie = Movie.find(params[:id])
render json: movie, status: 200, mime_type: Mime::Type.parse("video/mp4"),
content_type: "video/mp4"
end
private
def movie_params
params.require(:movie).permit(:title, :year, :plot, :video)
end
end
mime_types.rb
Mime::Type.register "video/mp4", :mp4
模型
class Movie < ApplicationRecord
has_attached_file :video, styles: {
medium: {
geometry: "640x480",
format: 'mp4' }
}, processors: [:transcoder]
validates_attachment :video, presence: true
do_not_validate_attachment_file_type :video
end
进行这些更改后,我使用curl命令测试并得到以下输出。
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sun, 29 Oct 2017 17:04:03 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
Location: http://localhost
Expires: Sun, 29 Oct 2017 17:04:02 GMT
Cache-Control: no-cache
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
HTTP/1.1 200 OK
Content-Type: video/mp4; charset=utf-8
ETag: W/"a8c0ff616394ec492839299f528b046c"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 01c9df7d-b878-4ea1-91a3-e22124d73d0c
X-Runtime: 0.022902
Vary: Origin
Transfer-Encoding: chunked
{"id":1,"title":"Test","plot":"Awesomeness","year":1977,"created_at":"2017-10-28T04:39:35.981Z","updated_at":"2017-10-28T04:39:35.981Z","video_file_name":"SampleVideo_720x480_1mb.mp4","video_content_type":"video/mp4","video_file_size":1057149,"video_updated_at":"2017-10-28T04:39:04.001Z"}
此输出有2种内容类型。我假设一个是提交,另一个是接收。第一个具有内容类型的text / html,而第二个具有video / mp4。所以,我再次检查Firefox仍然有相同的错误,视频仍然没有加载。
如果需要,可以从Angular前端洞察中获取一些相关代码。
服务
import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from "@angular/http"
import { Observable } from 'rxjs'
import { Movie } from './dvd'
import 'rxjs/add/operator/map'
// import { Movies } from './mock-dvd'
@Injectable()
export class DvdService {
moviesURL = 'http://localhost:3001/movies'
constructor(private http: Http) { }
getMovies(): Observable<Movie[]> {
return this.http.get(this.moviesURL)
.map((res: Response) => <Movie[]>res.json())
}
getMovie(id: number): Observable<Movie> {
return this.http.get(this.moviesURL + '/' + id + '.json')
.map((res: Response) => res.json())
}
}
成分</ P>
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute, Params, Router, ParamMap } from '@angular/router'
import { Location } from '@angular/common'
import { DvdService } from '../../dvd.service'
import { Movie } from '../../dvd'
import 'rxjs/add/operator/switchMap'
@Component({
selector: 'app-dvd-item',
templateUrl: './dvd-item.component.html',
styleUrls: ['./dvd-item.component.scss']
})
export class DvdItemComponent implements OnInit {
movie: Movie
id: number
constructor(private route: ActivatedRoute,
private location: Location,
private router: Router,
private dvdService: DvdService) {
}
ngOnInit(): void {
this.route.paramMap
.switchMap((params: ParamMap) => this.dvdService.getMovie(+params.get('id')))
.subscribe(movie => this.movie = movie);
}
}
模板
<div class="container">
<div class="row">
<div class="col-3">
<div *ngIf="movie">
<h6>{{ movie.title }}</h6>
<h6>{{ movie.video_file_name }}</h6>
<video width="640" height="480">
<source src="{{ movie.video }}" type="video/mp4">
</video>
</div>
</div>
</div>
</div>