Updates
This commit is contained in:
parent
3a47cb5dd8
commit
7e35d6a68e
3 changed files with 118 additions and 20 deletions
98
Dockerfile
98
Dockerfile
|
|
@ -2,6 +2,77 @@ FROM golang:1.13.6-alpine3.11 as builder
|
|||
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
# ffmpeg source - https://github.com/alfg/docker-ffmpeg
|
||||
ARG FFMPEG_VERSION=4.2.2
|
||||
ARG PREFIX=/opt/ffmpeg
|
||||
ARG LD_LIBRARY_PATH=/opt/ffmpeg/lib
|
||||
ARG MAKEFLAGS="-j4"
|
||||
|
||||
# FFmpeg build dependencies.
|
||||
RUN apk add --update \
|
||||
build-base \
|
||||
coreutils \
|
||||
freetype-dev \
|
||||
gcc \
|
||||
lame-dev \
|
||||
libogg-dev \
|
||||
libass \
|
||||
libass-dev \
|
||||
libvpx-dev \
|
||||
libvorbis-dev \
|
||||
libwebp-dev \
|
||||
libtheora-dev \
|
||||
opus-dev \
|
||||
pkgconf \
|
||||
pkgconfig \
|
||||
rtmpdump-dev \
|
||||
wget \
|
||||
x264-dev \
|
||||
x265-dev \
|
||||
yasm
|
||||
|
||||
# Get fdk-aac from testing.
|
||||
RUN echo http://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \
|
||||
apk add --update fdk-aac-dev
|
||||
|
||||
# Get ffmpeg source.
|
||||
RUN cd /tmp/ && \
|
||||
wget http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \
|
||||
tar zxf ffmpeg-${FFMPEG_VERSION}.tar.gz && rm ffmpeg-${FFMPEG_VERSION}.tar.gz
|
||||
|
||||
# Compile ffmpeg.
|
||||
RUN cd /tmp/ffmpeg-${FFMPEG_VERSION} && \
|
||||
./configure \
|
||||
--enable-version3 \
|
||||
--enable-gpl \
|
||||
--enable-nonfree \
|
||||
--enable-small \
|
||||
--enable-libmp3lame \
|
||||
--enable-libx264 \
|
||||
--enable-libx265 \
|
||||
--enable-libvpx \
|
||||
--enable-libtheora \
|
||||
--enable-libvorbis \
|
||||
--enable-libopus \
|
||||
--enable-libfdk-aac \
|
||||
--enable-libass \
|
||||
--enable-libwebp \
|
||||
--enable-librtmp \
|
||||
--enable-postproc \
|
||||
--enable-avresample \
|
||||
--enable-libfreetype \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--disable-ffplay \
|
||||
--extra-cflags="-I${PREFIX}/include" \
|
||||
--extra-ldflags="-L${PREFIX}/lib" \
|
||||
--extra-libs="-lpthread -lm" \
|
||||
--prefix="${PREFIX}" && \
|
||||
make && make install && make distclean
|
||||
|
||||
# Cleanup.
|
||||
RUN rm -rf /var/cache/apk/* /tmp/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY src src
|
||||
|
|
@ -13,17 +84,36 @@ RUN go build -x -o media-roller ./src
|
|||
|
||||
# youtube-dl needs python
|
||||
FROM python:3.8.1-alpine3.11
|
||||
RUN apk add --no-cache ffmpeg \
|
||||
curl && \
|
||||
ffmpeg -version
|
||||
|
||||
ENV PATH=/opt/ffmpeg/bin:$PATH
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
curl \
|
||||
ca-certificates \
|
||||
openssl \
|
||||
pcre \
|
||||
lame \
|
||||
libogg \
|
||||
libass \
|
||||
libvpx \
|
||||
libvorbis \
|
||||
libwebp \
|
||||
libtheora \
|
||||
opus \
|
||||
rtmpdump \
|
||||
x264-dev \
|
||||
x265-dev
|
||||
|
||||
COPY --from=builder /app/media-roller /app/media-roller
|
||||
COPY --from=builder /opt/ffmpeg /opt/ffmpeg
|
||||
COPY --from=builder /usr/lib/libfdk-aac.so.2 /usr/lib/libfdk-aac.so.2
|
||||
COPY templates /app/templates
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl && \
|
||||
chmod a+rx /usr/local/bin/youtube-dl && \
|
||||
youtube-dl --version
|
||||
youtube-dl --version && \
|
||||
ffmpeg -version
|
||||
|
||||
CMD /app/media-roller
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ type ResponseData struct {
|
|||
Id string
|
||||
}
|
||||
|
||||
// TODO: Use something better than this. It's too tedious to map
|
||||
var fetchResponseTmpl = template.Must(template.ParseFiles("templates/media/response.html"))
|
||||
var fetchIndexTmpl = template.Must(template.ParseFiles("templates/media/index.html"))
|
||||
|
||||
|
|
@ -59,14 +60,19 @@ func FetchMedia(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// returns the ID of the file
|
||||
func fetch(url string) (string, error) {
|
||||
// This will be the output file name
|
||||
// The id will be used as the name of the parent directory of the output files
|
||||
id := uuid.New().String()
|
||||
// youtube-dl will add the extension as needed
|
||||
name := getFilenameWithoutExtensionById(id)
|
||||
name := getMediaDirectory(id) + "%(title)s.%(ext)s"
|
||||
|
||||
log.Info().Msgf("Downloading %s to %s", url, id)
|
||||
|
||||
cmd := exec.Command("youtube-dl", "-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4/", "-o", name, url)
|
||||
cmd := exec.Command("youtube-dl",
|
||||
"--format", "bestvideo+bestaudio[ext=m4a]/bestvideo+bestaudio/best",
|
||||
"--merge-output-format", "mp4",
|
||||
"--restrict-filenames",
|
||||
"--write-info-json",
|
||||
"--output", name,
|
||||
url)
|
||||
|
||||
var stdoutBuf, stderrBuf bytes.Buffer
|
||||
stdoutIn, _ := cmd.StdoutPipe()
|
||||
|
|
@ -107,13 +113,6 @@ func fetch(url string) (string, error) {
|
|||
return id, nil
|
||||
}
|
||||
|
||||
// Returns the relative filename without the extension. Example:
|
||||
// downloads/b541cc43-9833-4146-ab19-71334484c0c1/media
|
||||
// where media can be media.mp4
|
||||
func getFilenameWithoutExtensionById(id string) string {
|
||||
return getMediaDirectory(id) + "media"
|
||||
}
|
||||
|
||||
// Returns the relative directory containing the media file, with a trailing slash
|
||||
// Id is expected to be pre validated
|
||||
func getMediaDirectory(id string) string {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package media
|
|||
import (
|
||||
"github.com/rs/zerolog/log"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -47,12 +49,20 @@ func getFileFromId(id string) (string, error) {
|
|||
files, _ := file.Readdirnames(0) // 0 to read all files and folders
|
||||
if len(files) == 0 {
|
||||
return "", errors.New("ID not found")
|
||||
} else if len(files) > 1 {
|
||||
// We should only have 1 media file produced
|
||||
} else if len(files) > 2 {
|
||||
// We should only have 2 media file produced, the mp4 and the json file
|
||||
return "", errors.New("internal error")
|
||||
}
|
||||
|
||||
return root + files[0], nil
|
||||
// We expect two files to be produced, a json manifest and an mp4. We want to return the mp4
|
||||
// Sometimes the video file might not have an mp4 extension, so filter out the json file
|
||||
for _, f := range files {
|
||||
if !strings.HasSuffix(f, ".json") {
|
||||
return root + f, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("unable to find file")
|
||||
}
|
||||
|
||||
func streamFileToClient(writer http.ResponseWriter, filename string) {
|
||||
|
|
@ -83,8 +93,7 @@ func streamFileToClient(writer http.ResponseWriter, filename string) {
|
|||
fileSize := strconv.FormatInt(fileStat.Size(), 10)
|
||||
|
||||
// Send the headers
|
||||
// Set the following if you want to force the client to download the file
|
||||
// writer.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filename))
|
||||
writer.Header().Set("Content-Disposition", "filename="+filepath.Base(filename))
|
||||
writer.Header().Set("Content-Type", fileContentType)
|
||||
writer.Header().Set("Content-Length", fileSize)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue