123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package agi
- import (
- "errors"
- "log"
- "os"
- "path/filepath"
- "github.com/robertkrimen/otto"
- uuid "github.com/satori/go.uuid"
- "imuslab.com/arozos/mod/agi/static"
- "imuslab.com/arozos/mod/agi/static/ffmpegutil"
- "imuslab.com/arozos/mod/utils"
- )
- /*
- AJGI FFmpeg adaptor Library
- This is a library for allow the use of ffmpeg via the arozos virtualized layer
- without the danger of directly accessing the bash / shell interface.
- Author: tobychui
- */
- func (g *Gateway) FFmpegLibRegister() {
- err := g.RegisterLib("ffmpeg", g.injectFFmpegFunctions)
- if err != nil {
- log.Fatal(err)
- }
- }
- func (g *Gateway) injectFFmpegFunctions(payload *static.AgiLibInjectionPayload) {
- vm := payload.VM
- u := payload.User
- scriptFsh := payload.ScriptFsh
- //scriptPath := payload.ScriptPath
- //w := payload.Writer
- //r := payload.Request
- vm.Set("_ffmpeg_conv", func(call otto.FunctionCall) otto.Value {
- //Get the input and output filepath
- vinput, err := call.Argument(0).ToString()
- if err != nil {
- g.RaiseError(err)
- return otto.FalseValue()
- }
- voutput, err := call.Argument(1).ToString()
- if err != nil {
- g.RaiseError(err)
- return otto.FalseValue()
- }
- if voutput == "" {
- //Output filename not provided. Not sure what format to convert
- g.RaiseError(err)
- return otto.FalseValue()
- }
- compression, err := call.Argument(2).ToInteger()
- if err != nil {
- //Do not use compression
- compression = 0
- }
- //Rewrite the vpath if it is relative
- vinput = static.RelativeVpathRewrite(scriptFsh, vinput, vm, u)
- voutput = static.RelativeVpathRewrite(scriptFsh, voutput, vm, u)
- //Translate the virtual path to realpath for the input file
- fsh, rinput, err := static.VirtualPathToRealPath(vinput, u)
- if err != nil {
- g.RaiseError(err)
- return otto.FalseValue()
- }
- //Translate the virtual path to realpath for the output file
- fsh, routput, err := static.VirtualPathToRealPath(voutput, u)
- if err != nil {
- g.RaiseError(err)
- return otto.FalseValue()
- }
- //Buffer the file to tmp
- //Note that even for local disk, it still need to be buffered to make sure
- //permission is in-scope as well as to avoid locking a file by child-process
- bufferedFilepath, err := fsh.BufferRemoteToLocal(rinput)
- if err != nil {
- g.RaiseError(err)
- return otto.FalseValue()
- }
- //fmt.Println(rinput, routput, bufferedFilepath)
- //Convert it to target format using ffmpeg
- outputTmpFilename := uuid.NewV4().String() + filepath.Ext(routput)
- outputBufferPath := filepath.Join(filepath.Dir(bufferedFilepath), outputTmpFilename)
- err = ffmpegutil.FFmpeg_conv(bufferedFilepath, outputBufferPath, int(compression))
- if err != nil {
- //FFmpeg conversion failed
- g.RaiseError(err)
- //Delete the buffered file
- os.Remove(bufferedFilepath)
- return otto.FalseValue()
- }
- if !utils.FileExists(outputBufferPath) {
- //Fallback check, to see if the output file actually exists
- g.RaiseError(errors.New("output file not found. Assume ffmpeg conversion failed"))
- //Delete the buffered file
- os.Remove(bufferedFilepath)
- return otto.FalseValue()
- }
- //Conversion completed
- //Delete the buffered file
- os.Remove(bufferedFilepath)
- //Upload the converted file to target disk
- src, err := os.OpenFile(outputBufferPath, os.O_RDONLY, 0755)
- if err != nil {
- g.RaiseError(err)
- //Delete the output buffer if failed
- os.Remove(outputBufferPath)
- return otto.FalseValue()
- }
- defer src.Close()
- err = fsh.FileSystemAbstraction.WriteStream(routput, src, 0775)
- if err != nil {
- g.RaiseError(err)
- //Delete the output buffer if failed
- os.Remove(outputBufferPath)
- return otto.FalseValue()
- }
- //Upload completed. Remove the remaining buffer file
- os.Remove(outputBufferPath)
- return otto.TrueValue()
- })
- vm.Run(`
- var ffmpeg = {};
- ffmpeg.convert = _ffmpeg_conv;
- `)
- }
|