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
|
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
|
WORKDIR /app
|
||||||
|
|
||||||
COPY src src
|
COPY src src
|
||||||
|
|
@ -13,17 +84,36 @@ RUN go build -x -o media-roller ./src
|
||||||
|
|
||||||
# youtube-dl needs python
|
# youtube-dl needs python
|
||||||
FROM python:3.8.1-alpine3.11
|
FROM python:3.8.1-alpine3.11
|
||||||
RUN apk add --no-cache ffmpeg \
|
|
||||||
curl && \
|
ENV PATH=/opt/ffmpeg/bin:$PATH
|
||||||
ffmpeg -version
|
|
||||||
|
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 /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
|
COPY templates /app/templates
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl && \
|
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 && \
|
chmod a+rx /usr/local/bin/youtube-dl && \
|
||||||
youtube-dl --version
|
youtube-dl --version && \
|
||||||
|
ffmpeg -version
|
||||||
|
|
||||||
CMD /app/media-roller
|
CMD /app/media-roller
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ type ResponseData struct {
|
||||||
Id string
|
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 fetchResponseTmpl = template.Must(template.ParseFiles("templates/media/response.html"))
|
||||||
var fetchIndexTmpl = template.Must(template.ParseFiles("templates/media/index.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
|
// returns the ID of the file
|
||||||
func fetch(url string) (string, error) {
|
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()
|
id := uuid.New().String()
|
||||||
// youtube-dl will add the extension as needed
|
name := getMediaDirectory(id) + "%(title)s.%(ext)s"
|
||||||
name := getFilenameWithoutExtensionById(id)
|
|
||||||
|
|
||||||
log.Info().Msgf("Downloading %s to %s", url, id)
|
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
|
var stdoutBuf, stderrBuf bytes.Buffer
|
||||||
stdoutIn, _ := cmd.StdoutPipe()
|
stdoutIn, _ := cmd.StdoutPipe()
|
||||||
|
|
@ -107,13 +113,6 @@ func fetch(url string) (string, error) {
|
||||||
return id, nil
|
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
|
// Returns the relative directory containing the media file, with a trailing slash
|
||||||
// Id is expected to be pre validated
|
// Id is expected to be pre validated
|
||||||
func getMediaDirectory(id string) string {
|
func getMediaDirectory(id string) string {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package media
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"net/http"
|
"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
|
files, _ := file.Readdirnames(0) // 0 to read all files and folders
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
return "", errors.New("ID not found")
|
return "", errors.New("ID not found")
|
||||||
} else if len(files) > 1 {
|
} else if len(files) > 2 {
|
||||||
// We should only have 1 media file produced
|
// We should only have 2 media file produced, the mp4 and the json file
|
||||||
return "", errors.New("internal error")
|
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) {
|
func streamFileToClient(writer http.ResponseWriter, filename string) {
|
||||||
|
|
@ -83,8 +93,7 @@ func streamFileToClient(writer http.ResponseWriter, filename string) {
|
||||||
fileSize := strconv.FormatInt(fileStat.Size(), 10)
|
fileSize := strconv.FormatInt(fileStat.Size(), 10)
|
||||||
|
|
||||||
// Send the headers
|
// Send the headers
|
||||||
// Set the following if you want to force the client to download the file
|
writer.Header().Set("Content-Disposition", "filename="+filepath.Base(filename))
|
||||||
// writer.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filename))
|
|
||||||
writer.Header().Set("Content-Type", fileContentType)
|
writer.Header().Set("Content-Type", fileContentType)
|
||||||
writer.Header().Set("Content-Length", fileSize)
|
writer.Header().Set("Content-Length", fileSize)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue