123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package agi
- import (
- "fmt"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "github.com/robertkrimen/otto"
- "imuslab.com/arozos/mod/agi/static"
- "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)
- }
- }
- /*
- FFmepg functions
- */
- func ffmpeg_conv(input string, output string, compression int) error {
- var cmd *exec.Cmd
- switch {
- case isVideo(input) && isVideo(output):
- // Video to video with resolution compression
- cmd = exec.Command("ffmpeg", "-i", input, "-vf", fmt.Sprintf("scale=-1:%d", compression), output)
- case (isAudio(input) || isVideo(input)) && isAudio(output):
- // Audio or video to audio with bitrate compression
- cmd = exec.Command("ffmpeg", "-i", input, "-b:a", fmt.Sprintf("%dk", compression), output)
- case isImage(output):
- // Resize image with width compression
- cmd = exec.Command("ffmpeg", "-i", input, "-vf", fmt.Sprintf("scale=%d:-1", compression), output)
- default:
- // Handle other cases or leave it for the user to implement
- return fmt.Errorf("unsupported conversion: %s to %s", input, output)
- }
- // Set the output of the command to os.Stdout so you can see it in your console
- cmd.Stdout = os.Stdout
- // Set the output of the command to os.Stderr so you can see any errors
- cmd.Stderr = os.Stderr
- // Run the command
- err := cmd.Run()
- if err != nil {
- return fmt.Errorf("error running ffmpeg command: %v", err)
- }
- return nil
- }
- // Helper functions to check file types
- func isVideo(filename string) bool {
- videoFormats := []string{
- ".mp4", ".mkv", ".avi", ".mov", ".flv", ".webm",
- }
- return utils.StringInArray(videoFormats, filepath.Ext(filename))
- }
- func isAudio(filename string) bool {
- audioFormats := []string{
- ".mp3", ".wav", ".aac", ".ogg", ".flac",
- }
- return utils.StringInArray(audioFormats, filepath.Ext(filename))
- }
- func isImage(filename string) bool {
- imageFormats := []string{
- ".jpg", ".png", ".gif", ".bmp", ".tiff", ".webp",
- }
- return utils.StringInArray(imageFormats, filepath.Ext(filename))
- }
- func main() {
- // Example usage
- err := ffmpeg_conv("input.mp4", "output.mp4", 720)
- if err != nil {
- fmt.Println("Error:", 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()
- }
- //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)
- return otto.TrueValue()
- })
- }
|