1

New to gRPC, I'm trying to stream a video file using grpc, both client and server are in Node, when running the service, I can console log the buffer on the server side, however I can't get anything from client side, Could anyone help me out, thanks!

video.proto:

syntax = "proto3";

package videoservice;

service VideoService {
  rpc callVideo (EmptyRequest) returns (stream VideoResponse);
}

message EmptyRequest {}

message VideoResponse {
  bytes videoStream = 1;
}

Implementation in server.js:

var PROTO_PATH = __dirname + '/video.proto';

var fs = require('fs');
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {keepCase: true,
     longs: String,
     enums: String,
     defaults: true,
     oneofs: true
    });
var videoservice = grpc.loadPackageDefinition(packageDefinition).videoservice;

function callVideo(call) {
    let videoDataStream = fs.createReadStream('./sample.mp4');
    videoDataStream.on('data',function(chunk){
        console.log(chunk);
        call.write(chunk);
    }).on('end',function(){
        call.end();
    })
}

function getServer() {
  var server = new grpc.Server();
  server.addService(videoservice.VideoService.service, {
    callVideo: callVideo
  });
  return server;
}

if (require.main === module) {
  // If this is run as a script, start a server on an unused port
  var videoServer = getServer();
  videoServer.bind('0.0.0.0:9090', grpc.ServerCredentials.createInsecure());
  videoServer.start();
}

exports.getServer = getServer;

and client.js:

var PROTO_PATH = __dirname + '/video.proto';

var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {keepCase: true,
     longs: String,
     enums: String,
     defaults: true,
     oneofs: true
    });
var vs = grpc.loadPackageDefinition(packageDefinition).videoservice;

const REMOTE_URL = "localhost:9090";
let client = new vs.VideoService(REMOTE_URL, grpc.credentials.createInsecure());

client.callVideo({}).on('data',function(chunk){
    console.log(chunk.videoStream);
});

Below is output, the left part is buffers' content in server side before going into gRPC channel, and the right part is the result in client side which has nothing in each chunk: enter image description here

Ethan Wang
  • 85
  • 2
  • 11

1 Answers1

3

This will help solve your problem:

function callVideo(call) {
    const videoDataStream = fs.createReadStream('./sample.mp4');

    videoDataStream.on('data', (chunk) => {
        console.log(chunk);
        call.write({ videoStream: chunk });
    });
    
    videoDataStream.on('end', () => {
        call.end();
    });
}

Do not pay attention to changing the style of the code. The main thing here is call.write({videoStream: chunk});.

Rustam D9RS
  • 3,236
  • 1
  • 10
  • 17
  • 1
    To add to this, the `video.proto` file describes the `VideoResponse` message as a message with a single field `videoStream` that has the type `bytes`. The object you send needs to look like it does in this answer to match the structure of that message definition. – murgatroid99 Jun 22 '20 at 16:03