2016-05-20 23 views
6

Tôi có tài liệu nhị phân (tệp video mp4) trong cơ sở dữ liệu (MarkLogic). Tôi đang sử dụng API Node.js của cơ sở dữ liệu để truyền tài liệu theo các khối. Quá trình cài đặt như sau:Node.js/Phát trực tuyến video nhanh (HTTP 206 Nội dung Một phần)

tập tin html

<video controls="controls" width="600"> 
    <source src="/video/myvideo.mp4" type="video/mp4"> 
</video> 

Trong nhanh Tôi có sau đó thiết lập một tuyến đường mà xử lý việc/video /: tuyến đường param (trong cơ sở dữ liệu video có định danh duy nhất đó là chuỗi '/video/myvideo.mp4')

Node.js

// I'm only showing the relevant things in here 

const serveVideo = (req, res) => { 
    var stream = db.documents.read('/gopro/malta.mp4').stream('chunked'); 

    var chunks = []; 
    var chunkBytes = 0; 
    var start = 0; 
    stream.on('data', (chunk) => { 
    var headers; 
    var range = req.headers.range; 
    var total = 214335483; //total length of vid in bytes 

    if (range) { 
     var chunkSize = chunk.length; 
     // (start === 0) ? start = 0 : start += chunkBytes; 
     if (chunkBytes === 0) { 
     start = 0 
     } else { 
     start = chunkBytes + 1 
     } 
     chunkBytes += chunkSize; 

     headers = { 
     'Content-Range': 'bytes ' + start + '-' + chunkBytes + '/' + total, 
     'Accept-Ranges': 'bytes', 
     'Content-Length': chunkSize, 
     'Content-Type': 'video/mp4' 
     }; 
     res.writeHead(206, headers); 
     chunks.push(chunk); 
    } 
    }); 
    stream.on('end',() => { 
    var allChunks = Buffer.concat(chunks); 
    res.end(allChunks); 
    }); 
}); 


router.route('/video/:uri').get(serveVideo); 

Bây giờ tất nhiên ở trên thất bại với 'Lỗi: Không thể đặt tiêu đề sau khi chúng được gửi đi.' đó là tất cả công bằng và vuông. Nhưng tôi không thể có được đầu của tôi xung quanh này - .stream ('chunked') gọi lực lượng cơ sở dữ liệu để lấy tài liệu trong khối và tôi thấy những khối chỉ tốt, tuy nhiên làm thế nào tôi có thể trả lại một 206 cho trình duyệt? Tôi không thể làm điều đó trong .on ('dữ liệu') khi dữ liệu đang được truyền trực tuyến để tiêu đề sẽ được gửi nhiều lần. Tôi đoán cơ sở dữ liệu nào tôi đang sử dụng không thực sự có liên quan - tôi muốn hiểu khái niệm này, hoặc ít nhất là xem tôi đang làm gì sai.

Mọi trợ giúp đều được đánh giá cao. Tất cả các ví dụ và các cuộc thảo luận khác mà tôi đã thấy rằng luồng video bằng cách sử dụng Node.js đang đọc tệp video từ đĩa.

cập nhật

Làm một sự thay đổi để mã bây giờ cho phép FF để phát video nhưng không phải Chrome:

let stream = db.documents.read({uris:'/gopro/malta.mp4'}).stream('chunked'); 
stream.pipe(res); 

Không có lỗi trong giao diện điều khiển của Chrome. Sau đây là các chi tiết tiêu đề - lưu ý rằng có hai yêu cầu cho các tập tin mp4:

1st

Response Headers 
Connection:keep-alive 
Date:Sat, 21 May 2016 17:05:30 GMT 
Transfer-Encoding:chunked 
X-Powered-By:Express 

Request Headers 
view source 
Accept:*/* 
Accept-Encoding:identity;q=1, *;q=0 
Accept-Language:en-US,en;q=0.8,hu;q=0.6,ro;q=0.4,it;q=0.2 
Cache-Control:no-cache 
Connection:keep-alive 
Cookie:__distillery=v20150227_a8e22306-65b3-4c2e-9a8a-159e308156ad; __smToken=7nYU8NYQY15mPowjjCZsS5D3 
DNT:1 
Host:localhost:8080 
Pragma:no-cache 
Range:bytes=0- 
Referer:http://localhost:8080/ 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 
Response Headers 
Connection:keep-alive 
Date:Sat, 21 May 2016 17:05:31 GMT 
Transfer-Encoding:chunked 
X-Powered-By:Express 

Request Headers 
view source 
Accept:*/* 
Accept-Encoding:identity;q=1, *;q=0 
Accept-Language:en-US,en;q=0.8,hu;q=0.6,ro;q=0.4,it;q=0.2 
Cache-Control:no-cache 
Connection:keep-alive 
Cookie:__distillery=v20150227_a8e22306-65b3-4c2e-9a8a-159e308156ad; __smToken=7nYU8NYQY15mPowjjCZsS5D3 
DNT:1 
Host:localhost:8080 
Pragma:no-cache 
Range:bytes=28- 
Referer:http://localhost:8080/ 
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 
+0

Bạn đã chứng minh rằng mã của bạn ở trên hoạt động bằng cách đọc từ đĩa? Tôi đề nghị rằng đây là bước đầu tiên của xử lý sự cố. Một khi bạn phá vỡ trở lại rằng mã chung là âm thanh, sau đó thêm các bước DB trở lại. –

+0

Câu hỏi hay! Tôi d nói rằng bạn không nên gọi cho writeHead, nhưng bạn sẽ cần phải đào sâu vào thể hiện để viết tiêu đề trực tiếp. Bạn cũng có thể xem [code] này (https://github.com/feross/webtorrent/blob/c85dd3b83bdbd7fcbbb32c65a080b7011e4daede/lib/server.js) mà tôi biết có thể truyền trực tuyến video với 206 câu trả lời, nó được sử dụng trong peerflix . xem thêm https://gist.github.com/paolorossi/1993068 –

+0

Bạn hầu như không cần tất cả các nội dung. Đặt tiêu đề theo cách thủ công: 'res.status (206);'. Sau đó, đơn giản là trả lời cho câu lệnh: 'let stream = db.yourChunkStuff(); stream.pipe (res); '. Trên điện thoại ở đây để không thể kiểm tra, do đó, chỉ đưa nó vào một bình luận ngay bây giờ. – Zlatko

Trả lời

4

Các on ('dữ liệu') gọi lại có thể luôn luôn có một kết thúc trên một biến isFirstChunk được khởi tạo đúng và có một thử nghiệm, nếu isFirstChunk là true, phát ra các tiêu đề và đặt làFirstChunk thành false.

Sẽ tốt hơn nếu bạn đặt đường ống nếu có thể. npm có thể cung cấp một thư viện stream (có thể là through2()?) có một sự kiện khi dữ liệu đầu tiên đến.

Đối với thời hạn dài hơn, bạn có thể hợp lý gửi RFE cho sự kiện ở đầu luồng.

Hy vọng điều đó sẽ giúp,

3

Bạn rất có thể không cần tất cả các nội dung. Đặt tiêu đề bằng tay:

res.status(206); 

Sau đó chỉ cần ống phản ứng:

let stream = db.yourChunkStuff(); 
stream.pipe(res); 

Cách đơn giản nhất để là suối ống.

Các vấn đề liên quan