2014-02-21 2 views
2

나는 sails.js에서 제공하는 서버에 오디오 파일을 보내는 응용 프로그램을 작성 중입니다.업로드 된 파일을 즉시 변환하여 돛 내에서 Amazon S3로 직접 스트리밍 할 수 있습니다

이 오디오 파일을 변환하고 노드 스트림을 사용하여 변환 된 데이터를 아마존 S3에 보내야합니다.

서버에 데이터를 저장하는 대신 변환 된 파일을 S3으로 직접 스트리밍하고 싶습니다.

그 방법을 알고 계십니까?

나는 강력 함을 시도했지만 제대로 작동하지 못했습니다. 누구든지 그런 일을 성공 시켰습니까?

감사

편집

jibsales가 발견으로 난 당신에게 내가 지금까지 시도했다 조각을 보여 주면, 아마 더 좋을 것이다. 그래서 기본적으로 전략은 강력하고 유창한 ffmpeg와 knox를 스트림과 함께 사용하는 것입니다.

나는 fluid-ffmpeg로 변환하기위한 엔트리 포인트가 될 첫 번째 스트림 (스트림 1)에 수신 가능한 데이터 덩어리를 작성하고 강력한 파일 스트림을 수신 할 계획입니다. 그런 다음 fluent-ffmpeg은 출력 스트림을 Knox의 진입 점 인 stream2에 씁니다.

내가 직면해야 할 첫 번째 문제는 강력한 것으로 작동하지 않는다는 사실입니다. 그러나 나는

코드는 지금까지 다음과 같습니다 ... 내 전략은 잘 모르겠어요 :

upload : function(req,res){ 

    //to streams to transfer file data 
    var stream1 = new stream.Stream(); //stream for the incoming file data 
    var stream2 = new stream.Stream(); //stream for the converted file data 

    var client = knox.createClient({ 
      key: 'APIKEY' 
      , secret: 'SECRET' 
      , bucket: 'bucket' 
     }); 

    //Using formidable to acces data chunks 
    var form = new formidable.IncomingForm(); 

    form.parse(req, function(err, fields, files){ //form.parse is not called 
    if(err){ 
     return res.json(err); 
    }else{ 
     return res.send('ok');  
    } 
    }); 

    //overriding form.onPart to get the file data chunk 
    form.onPart = function(part) { 
     sails.log('getting part...'); 

     if (!part.filename) { 
      form.handlePart(part); 
      return; 
     } 
     //we put the data chunk in stream1 to convert it 
     part.on('data', function(chunk) { 
      stream1.write(chunk[1]); 
     }); 
    } 

    form.on('error',function(err){ 
    return sails.log(err); 
    }); 

    form.on('progress', function(bytesReceived, bytesExpected) { 
    sails.log(bytesReceived); 
    }); 

    //conversion process 
    var proc = new ffmpeg({ source : stream1}) 
    .withAudioCodec('libfdk_aac') 
    .toFormat('mp3') 
    .writeToStream(stream2, {end:true}, function(retcode, error){ 
    console.log('file has been converted succesfully'); 
    }); 


client.putStream(stream2, '/file.mp3', headers, function(err, response){ 
    return res.send(response); 
}); 

}, 
+0

Google에서 사용자에게 답변을 제안하는 대신 코드를 작성해야합니다. 코드 작성 서비스가 아닙니다. – srquinn

+0

코드 작성을 요구하는 것이 아니라 그것을 수행하는 방법에 대한 단서를 묻는 중입니다 ... 미안 완벽하게 구현 된 대답을 기대한다고 생각하면 죄송합니다. 나는 당신에게 도움이 될 수 있다면 더 많은 통찰력을 줄 수있는 나의 시도로 나의 질문을 업데이트 할 것이다 ... – adc06

답변

1

유창한 -ffmpeg 및 강력 함으로 파일을 변환하는 방법을 알아 냈습니다. 그러나 변환하는 동안 알 수없는 "Content-Length"헤더가 정확히 있어야하므로 즉시 ffmpeg 변환에서 아마존으로 변환되는 변환 된 청크를 스트리밍하는 것은 불가능한 것 같습니다.

첫 번째 부분 내가 먼저 설정/express.js 파일의 업로드 경로에 명시 bodyParser을 해제했다) 업로드 :

var express = require('sails/node_modules/express'); 

module.exports.express = { 
    bodyParser: function() { 
    return function (req, res, next){ 
     console.log(req.path); 
     if (!(req.path === '/upload' && req.method === 'POST')) { 
     return express.bodyParser()(req, res, next); 
     } else { 
     return next(); 
     } 
    } 
    } 
} 

을 나는 기본적으로 아무것도하지 않는 스트림을 변환에 사용되는 구현을 위해.업로드 된 데이터 (파일 데이터와 관련된 데이터)의 올바른 부분 만 가져옵니다. 강력한 파서와 유창한 -fmpeg를 연결합니다. 그럼 난 단지 녹스 - MPU는 당신이 실제로 아마존 S3 직접 데이터를 스트리밍 할 수 있습니다 사용 ... 아마존에 보내기 전에

upload : function(req,res){ 

    var Transform = Stream.Transform; //stream for the incoming file data 
    var client = knox.createClient({ 
      key: 'KEY' 
      , secret: 'SECRET' 
      , bucket: 'BUCKET', 
      region : 'eu-west-1' //don't forget the region (My bucket is in Europe) 
     }); 


    function InputStream(options) 
    { 
      if(!(this instanceof InputStream)) 
      { 
      return new InputStream(options); 
      } 
      Transform.call(this,options); 
      return; 
    }; 

    util.inherits(InputStream, Transform); 

    var inputDataStream = new InputStream; 

    var form = new formidable.IncomingForm(); 

    form.parse(req, function(err, fields, files) 
    { 
    if(err){ 
     return res.send(err); 
    }else{ 
     return;  
    } 
    }); 

    form.onPart = function(part) 
    { 
     if (!part.filename) 
     { 
      form.handlePart(part); 
      return; 
     } 
     //we put the data chunk in stream1 to convert it 
     part.on('data', function (chunk) 
     { 
      if(!inputDataStream.write(chunk)); 
      form.pause() 
      inputDataStream.once('drain', function(){form.resume()}); 
     }); 

     part.on('end', function (chunk){ 
      inputDataStream.end(chunk); 
     }); 

    } 

    InputStream.prototype._transform = function (chunk, enc, cb) 
    { 
    this.push(chunk); 
    cb(); 
    } 

    var proc = new ffmpeg({ source : inputDataStream}) 
     .withAudioBitrate('64k') 
     .withAudioCodec('libmp3lame') 
     .toFormat('mp3') 
     .saveToFile('file.mp3', function (retcode, error){ 
     console.log('file has been converted successfully'); 
     res.send('ok'); 
      var upload = new MultiPartUpload(
      { 
      client : client, 
      objectName: 'file.mp3', 
      file: 'file.mp3' 
      }, function(err,body){ 
      if(err) { 
       console.log(err); 
       return; 
      } 
      console.log(body); 
      return; 
      }); 

     }); 
    }, 

편집

을 디스크에 변환 된 파일을 저장할 수 있습니다! 업로드의 소스가 될 또 다른 변환 스트림을 만들어야하고, knox-mpu가 마술을합니다. 다 감사합니다!

+0

S3로 스트리밍하기 위해 Knox MPU 모듈을 사용해보십시오. 아마존의 다중 부분 업로드 API를 사용하는 경우 콘텐츠 길이가 미리 필요하지 않을 것입니다. – sgress454

+0

예, 방금 발견했습니다! 대단 하네! 나는 곧 답변을 업데이트 할 것입니다 ... 마지막 문제는 동시 업로드에 관한 것입니다 ... – adc06

4
강력한 이유가 작동하지 않는

는 기본 돛 본체 파서가 요청을 구문 분석이다 강력하기 전에 그것에 도달 할 수 있습니다. 이 기능을 사용하려면 여러 부분으로 구성된 양식 업로드를 위해 Sails 본문 파서를 무시해야합니다. 그래서, config/express.js에서 다음 content-type 헤더 multipart/form-data가 포함 된 경우

var express = require('sails/node_modules/express'); 
    module.exports.express = { 
     bodyParser: function(options) { 
     return function (req, res, next) { 
      if (!req.headers['content-type'] || req.headers['content-type'].indexOf('multipart/form-data') === -1) { 
      return express.bodyParser()(req, res, next); 
      } else { 
      return next(); 
      } 
     } 
     } 
    } 

이것은 단지 완전히 몸 파서를 건너 뜁니다. 그렇지 않으면 기본 표현형 본문 파서를 실행합니다. 기본 Sails 본문 파서는 Express와 함께 제공되는 것보다 약간 더 멋지다는 점에 유의하십시오 (요청을 구문 분석 할 수 없으면 application/json 헤더를 가짜로 만들고 재 시도 함). 따라서 여분의 선을 원하면 복사/붙여 넣기를해야합니다. 코드를 코어에서 위의 bodyParser 함수로 바꿉니다. 하지만 대부분의 경우에는 그것을 놓치지 않을 것입니다 .-)

우리는 더 나은 파일 파서를 개발하고 있습니다. !

+0

감사합니다 스콧, 나는 당신의 솔루션을 시험해 보았다. 잠시 동안 내 앱을 들었을 때 오류가 발생했다 ... req.headers 정의되지 않는 것 같습니다 ... 나는 여전히 작동 시키려고 노력하고 있습니다! 그 외에도 제 질문에 대한 해결책은 제 자리에 배치하기가 약간 어려워 보입니다. 제 질문을 향상 시키려고 노력할 것입니다. – adc06

+0

좋습니다. 문제가 해결되면 bodyParser는 인수를 취하고 인수가 req, res, next 인 함수를 반환하는 함수 여야합니다. 내 질문이 업데이트 될 때 나타납니다. 고마워요! – adc06

관련 문제