Skip to content

Commit c318f3b

Browse files
authored
Merge pull request #3 from klahaha/tests
Some refactoring
2 parents f004def + e03ddf9 commit c318f3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+892
-815
lines changed

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
bin/
2-
streams.yaml
1+
config.yml
2+
config.yaml
3+
go-transcode
4+
bin
5+
.env

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ RUN set -eux; apt update; \
1717
COPY . .
1818

1919
RUN go get -v -t -d .; \
20-
./build
20+
go build -o bin/go-transcode
2121

2222
ENV TRANSCODE_BIND=:8080
2323

24-
ENTRYPOINT [ "bin/transcode" ]
24+
ENTRYPOINT [ "bin/go-transcode" ]
2525
CMD [ "serve" ]

Dockerfile.nvidia

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ RUN groupadd --gid $USER_GID $USERNAME; \
1414
useradd --uid $USER_UID --gid $USERNAME --shell /bin/bash --create-home $USERNAME;
1515

1616
COPY --from=build /app/bin bin
17-
COPY profiles_nvidia profiles
17+
COPY profiles profiles
1818
COPY data data
1919

2020
ENV USER=$USERNAME

README.md

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,65 @@
1-
# Go live HTTP on-demand transcoding
2-
Transcoding is expensive and resource consuming operation on CPU and GPU. For big companies with thousands of customers it is essential, to have a dedicated 24/7 transcoding servers. But we, single sporadic users of transcoding, need to have different approach. Transcoding should be done only when its output is really needed. This tool is trying to solve this problem by offering transcoding on demand.
1+
# go-transcode HTTP on-demand transcoding API
32

4-
This tool is intended to be used with live streams only. Seeking is not supported, yet.
3+
## Why
4+
5+
Transcoding is expensive and resource consuming operation on CPU and GPU. For big companies with thousands of customers it is essential, to have a dedicated 24/7 transcoding servers which can store all the transcoded versions.
6+
7+
For the rest of us who don't have infinite resources and cannot have 3 times bigger media library because of transcoding, we should only transcode when it is needed. This tool is trying to solve this problem by offering transcoding on demand.
8+
9+
This feature is common in media centers (plex, jellyfin) but there was no simple transcoding server without all other media center features. Now there is one! go-transcode is simple and extensible, and will probably not add features unrelated to transcoding.
10+
11+
## Features
12+
13+
Sources:
14+
- [x] Live streams
15+
- [ ] Static files (basic support)
16+
- [x] Any codec/container supported by ffmpeg
17+
18+
Outputs:
19+
- [x] Basic MP4 over HTTP (h264+aac) : `http://go-transcode/[profile]/[stream-id]`
20+
- [x] Basic HLS over HTTP (h264+aac) : `http://go-transcode/[profile]/[stream-id]/index.m3u8`
21+
- [x] Demo HTML player (for HLS) : `http://go-transcode/[profile]/[stream-id]/play.html`
22+
23+
Features:
24+
- [ ] Seeking for static files (index)
25+
- [ ] Audio/Subtitles tracks
26+
- [ ] Private mode (serve users authenticated by reverse proxy)
527

628
## Config
7-
Specify streams as object in yaml file.
829

9-
### Streams
10-
Create `streams.yaml` file, with your streams:
30+
Place your config file in `./config.yaml` (or `/etc/transcode/config.yaml`). The streams are defined like this:
1131

1232
```yaml
1333
streams:
1434
<stream-id>: <stream-url>
1535
```
1636
17-
Example:
37+
Full configuration example:
38+
1839
```yaml
40+
# allow debug outputs
41+
debug: true
42+
43+
# bind server to IP:PORT (use :8888 for all connections)
44+
bind: localhost:8888
45+
46+
# serve static files from this directory (optional)
47+
static: /var/www/html
48+
49+
# TODO: issue #4
50+
proxy: true
51+
1952
streams:
2053
cam: rtmp://localhost/live/cam
2154
ch1_hd: http://192.168.1.34:9981/stream/channelid/85
2255
ch2_hd: http://192.168.1.34:9981/stream/channelid/43
2356
```
2457
25-
HTTP streaming is accessible via:
26-
- `http://localhost:8080/<profile>/<stream-id>`
27-
28-
HLS is accessible via:
29-
- `http://localhost:8080/<profile>/<stream-id>/index.m3u8`
30-
- `http://localhost:8080/<profile>/<stream-id>/play.html`
31-
32-
## CPU Profiles
33-
Profiles (HTTP and HLS) with CPU transcoding can be found in `profiles`:
58+
## Transcoding profiles
3459
35-
* h264_360p
36-
* h264_540p
37-
* h264_720p
38-
* h264_1080p
60+
go-transcode supports any formats that ffmpeg likes. We provide profiles out-of-the-box for h264+aac (mp4 container) for 360p, 540p, 720p and 1080p resolutions: `h264_360p`, `h264_540p`, `h264_720p` and `h264_1080p`. Profiles can have any name, but must match regex: `^[0-9A-Za-z_-]+$`
3961

40-
Profile names must match flowing regex: `^[0-9A-Za-z_-]+$`
41-
42-
## GPU Profiles
43-
Profiles (HTTP and HLS) with GPU transcoding can be found in `profiles_nvidia`:
44-
45-
* h264_360p
46-
* h264_540p
47-
* h264_720p
48-
* h264_1080p
49-
50-
Profile names must match flowing regex: `^[0-9A-Za-z_-]+$`
62+
In these profile directories, actual profiles are located in `hls/` and `http/`, depending on the output format requested. The profiles scripts detect hardware support by running ffmpeg. No special config needed to use hardware acceleration.
5163

5264
## Docker
5365

@@ -63,7 +75,7 @@ docker build -t go-transcode:latest .
6375
docker run --rm -d \
6476
--name="go-transcode" \
6577
-p "8080:8080" \
66-
-v "${PWD}/streams.yaml:/app/streams.yaml" go-transcode:latest
78+
-v "${PWD}/config.yaml:/app/config.yaml" go-transcode:latest
6779
```
6880

6981
## Nvidia GPU support (docker)
@@ -85,7 +97,7 @@ docker run --rm -d \
8597
--gpus=all \
8698
--name="go-transcode-nvidia" \
8799
-p "8080:8080" \
88-
-v "${PWD}/streams.yaml:/app/streams.yaml" go-transcode-nvidia:latest
100+
-v "${PWD}/config.yaml:/app/config.yaml" go-transcode-nvidia:latest
89101
```
90102

91103
### Supported inputs
@@ -103,3 +115,34 @@ Input codec will be automatically determined from given stream. Please check you
103115
| vc1 | vc1_cuvid | SMPTE VC-1 |
104116
| vp8 | vp8_cuvid | On2 VP8 |
105117
| vp9 | vp9_cuvid | Google VP9 |
118+
119+
## Alternatives
120+
121+
- [nginx-vod-module](https://github.com/kaltura/nginx-vod-module): Only supports MP4 sources.
122+
- [tvheadend](https://tvheadend.org/): Intended for various live sources (IPTV or DVB), not media library - although it can record TV. Supports Nvidia acceleration, but it is hard to compile.
123+
- [jellyfin](https://github.com/jellyfin/jellyfin): Supports live TV sources, although does not work realiably. Cannot run standalone transcoding service (without media library).
124+
- Any suggestions?
125+
126+
## Contribute
127+
128+
Join us in the [Matrix space](https://matrix.to/#/#go-transcode:proxychat.net) (or the [#go-transcode-general](https://matrix.to/#/#go-transcode-general:proxychat.net) room directly) or [via XMPP bridge](xmpp:#go-transcode-general#[email protected]).
129+
130+
## Architecture
131+
132+
The source code is in the following files/folders:
133+
134+
- `cmd/` and `main.go`: source for the command-line interface
135+
- `hls/`: process runner for HLS transcoding
136+
- `internal/`: actual source code logic
137+
138+
*TODO: document different modules/packages and dependencies*
139+
140+
Other files/folders in the repositories are:
141+
142+
- `data/`: files used/served by go-transcode
143+
- `dev/`: some docker helper scripts
144+
- `profiles/`: the ffmpeg profiles for transcoding
145+
- `tests/`: some tests for the project
146+
- `Dockerfile`, `Dockerfile.nvidia` and `docker-compose.yaml`: for the docker lovers
147+
- `god.mod` and `go.sum`: golang dependencies/modules tracking
148+
- `LICENSE`: licensing information (Apache 2.0)

build

Lines changed: 0 additions & 3 deletions
This file was deleted.

cmd/root.go

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import (
44
"os"
55
"runtime"
66

7+
"github.com/fsnotify/fsnotify"
78
"github.com/rs/zerolog"
89
"github.com/rs/zerolog/log"
910
"github.com/spf13/cobra"
1011
"github.com/spf13/viper"
1112

12-
"github.com/m1k1o/go-transcode"
13+
transcode "github.com/m1k1o/go-transcode/internal"
1314
)
1415

1516
func Execute() error {
@@ -24,59 +25,59 @@ var root = &cobra.Command{
2425

2526
func init() {
2627
cobra.OnInitialize(func() {
28+
config := transcode.Service.RootConfig
29+
config.Set()
30+
2731
//////
2832
// logs
2933
//////
30-
zerolog.TimeFieldFormat = ""
31-
zerolog.SetGlobalLevel(zerolog.InfoLevel)
34+
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
35+
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
3236

33-
if viper.GetBool("debug") {
37+
if config.Debug {
3438
zerolog.SetGlobalLevel(zerolog.DebugLevel)
39+
} else {
40+
zerolog.SetGlobalLevel(zerolog.InfoLevel)
3541
}
3642

37-
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stdout})
38-
3943
//////
4044
// configs
4145
//////
42-
config := viper.GetString("config")
43-
if config != "" {
44-
viper.SetConfigFile(config) // Use config file from the flag.
46+
if config.CfgFile != "" {
47+
viper.SetConfigFile(config.CfgFile) // use config file from the flag
4548
} else {
4649
if runtime.GOOS == "linux" {
4750
viper.AddConfigPath("/etc/transcode/")
4851
}
4952

5053
viper.AddConfigPath(".")
51-
viper.SetConfigName("transcode")
54+
viper.SetConfigName("config")
5255
}
5356

5457
viper.SetEnvPrefix("transcode")
5558
viper.AutomaticEnv() // read in environment variables that match
5659

57-
if err := viper.ReadInConfig(); err != nil {
58-
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
59-
log.Error().Err(err)
60-
}
61-
if config != "" {
62-
log.Error().Err(err)
63-
}
60+
err := viper.ReadInConfig()
61+
if err != nil && config.CfgFile != "" {
62+
log.Err(err)
6463
}
6564

66-
file := viper.ConfigFileUsed()
6765
logger := log.With().
68-
Bool("debug", viper.GetBool("debug")).
69-
Str("logging", viper.GetString("logs")).
70-
Str("config", file).
66+
Bool("debug", config.Debug).
7167
Logger()
7268

73-
if file == "" {
74-
logger.Warn().Msg("preflight complete without config file")
69+
file := viper.ConfigFileUsed()
70+
if file != "" {
71+
viper.OnConfigChange(func(e fsnotify.Event) {
72+
log.Info().Msg("config file reloaded")
73+
transcode.Service.ConfigReload()
74+
})
75+
76+
viper.WatchConfig()
77+
logger.Info().Str("config", file).Msg("preflight complete with config file")
7578
} else {
76-
logger.Info().Msg("preflight complete")
79+
logger.Warn().Msg("preflight complete without config file")
7780
}
78-
79-
transcode.Service.RootConfig.Set()
8081
})
8182

8283
if err := transcode.Service.RootConfig.Init(root); err != nil {

cmd/serve.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import (
44
"github.com/rs/zerolog/log"
55
"github.com/spf13/cobra"
66

7-
"github.com/m1k1o/go-transcode"
8-
"github.com/m1k1o/go-transcode/internal/config"
7+
"github.com/m1k1o/go-transcode/internal"
98
)
109

1110
func init() {
@@ -16,21 +15,13 @@ func init() {
1615
Run: transcode.Service.ServeCommand,
1716
}
1817

19-
configs := []config.Config{
20-
transcode.Service.ServerConfig,
21-
}
22-
2318
cobra.OnInitialize(func() {
24-
for _, cfg := range configs {
25-
cfg.Set()
26-
}
19+
transcode.Service.ServerConfig.Set()
2720
transcode.Service.Preflight()
2821
})
2922

30-
for _, cfg := range configs {
31-
if err := cfg.Init(command); err != nil {
32-
log.Panic().Err(err).Msg("unable to run serve command")
33-
}
23+
if err := transcode.Service.ServerConfig.Init(command); err != nil {
24+
log.Panic().Err(err).Msg("unable to run serve command")
3425
}
3526

3627
root.AddCommand(command)

cmd/transcode/main.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

dev/start

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ docker run --rm -it \
66
-p "3005:8080" \
77
-v "${PWD}/../:/app" \
88
--entrypoint="/bin/bash" \
9-
transcode_server_img -c '/app/build && ./bin/transcode serve --bind :8080';
9+
--workdir="/app" \
10+
transcode_server_img -c 'go build && ./go-transcode serve --bind :8080';

docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ services:
88
ports:
99
- "8080:8080"
1010
volumes:
11-
- ./streams.yaml:/app/streams.yaml
11+
- ./config.yaml:/app/config.yaml
1212
command: serve -d

0 commit comments

Comments
 (0)