From ce2baaca4b42cd57dc2e5078f1791d1f25c4bea1 Mon Sep 17 00:00:00 2001 From: 502647092 Date: Wed, 21 Nov 2018 18:57:30 +0800 Subject: [PATCH] Create & Init Project... --- Dockerfile | 18 +++++++++ go.mod | 1 + main.go | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Dockerfile create mode 100644 go.mod create mode 100644 main.go diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d9d7f46 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM golang:alpine AS build + +WORKDIR /go/src/github.com/yumc.pw/cloud/ffmpeg-webapi +ADD main.go . +RUN go build -o main + +FROM alpine:edge +LABEL maintainer="MiaoWoo" + +WORKDIR /root + +RUN set -x && \ + apk add --no-cache ca-certificates yasm ffmpeg && \ + rm -rf /var/cache/apk/* + +COPY --from=build /go/src/github.com/yumc.pw/cloud/ffmpeg-webapi/main ./main + +CMD ./main diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d9b3849 --- /dev/null +++ b/go.mod @@ -0,0 +1 @@ +module yumc.pw/cloud/ffmpeg-webapi diff --git a/main.go b/main.go new file mode 100644 index 0000000..a2b0b63 --- /dev/null +++ b/main.go @@ -0,0 +1,114 @@ +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)) +}