package main import ( "crypto/md5" "encoding/hex" "flag" "fmt" "io" "io/ioutil" "net/http" "os" "os/exec" "strconv" "strings" ) var tempDir *string var ffmpeg = "ffmpeg" func main() { b := flag.String("b", ":8080", "Server Bind Address") tempDir = flag.String("temp", os.TempDir(), "") flag.Parse() if _, err := exec.LookPath(ffmpeg); err != nil { fmt.Printf("Error Can't Find %s Client...", ffmpeg) return } http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) { if strings.HasPrefix(req.RequestURI, "/amr2mp3") { amr2mp3(resp, req) return } api(resp, req) }) http.ListenAndServe(*b, nil) fmt.Printf("FFmpeg WebInterface Listen on %s ...\n", *b) } func api(w http.ResponseWriter, r *http.Request) { handleInternal(w, r, r.FormValue("o"), r.FormValue("t")) } func amr2mp3(w http.ResponseWriter, r *http.Request) { handleInternal(w, r, "amr", "mp3") } func handleInternal(w http.ResponseWriter, r *http.Request, origin, target string) { // Read Byte From File Or URL bytes, err := readBytesFromRequest(r) if err != nil { w.Write([]byte("Error Read Bytes: " + err.Error())) return } // Convert origin to target out, err := convert(bytes, origin, target) if err != nil { w.Write([]byte("Error Handler: " + err.Error())) return } w.Write(out) } func convert(in []byte, origin, target string) (out []byte, err error) { source := *tempDir + "/" + fmt.Sprintf("ffmpeg-webapi-%s-%s", MD5(in), strconv.Itoa(len(in))) amr := source + "." + origin ioutil.WriteFile(amr, in, os.ModeAppend) defer os.Remove(amr) mp3 := source + "." + target err = exec.Command(ffmpeg, "-i", amr, mp3).Run() defer os.Remove(mp3) if err != nil { // Ignore Error Bucause ffmpeg will return not zero when amr to mp3 } // check target file is exist if not maybe exec error if _, err := exec.LookPath(mp3); err == nil { return nil, err } return ioutil.ReadFile(mp3) } func readBytesFromRequest(r *http.Request) (out []byte, err error) { var reader io.Reader url := r.FormValue("url") if url != "" { fmt.Printf("[A2M] url request " + url + "\n") var resp *http.Response resp, err = http.Get(url) if err != nil { return nil, err } reader = resp.Body } else { fmt.Printf("[A2M] file request\n") reader, _, err = r.FormFile("file") if err != nil { return nil, err } } return ioutil.ReadAll(reader) } // MD5 生成32位MD5 func MD5(bytes []byte) string { ctx := md5.New() ctx.Write(bytes) return hex.EncodeToString(ctx.Sum(nil)) }