diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index 8348d09ad..5efc7009d 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -6,8 +6,9 @@
 package cmd
 
 import (
+	"github.com/deluan/navidrome/core"
+	"github.com/deluan/navidrome/core/transcoder"
 	"github.com/deluan/navidrome/engine"
-	"github.com/deluan/navidrome/engine/transcoder"
 	"github.com/deluan/navidrome/persistence"
 	"github.com/deluan/navidrome/scanner"
 	"github.com/deluan/navidrome/server"
@@ -40,11 +41,11 @@ func CreateAppRouter() *app.Router {
 func CreateSubsonicAPIRouter() (*subsonic.Router, error) {
 	dataStore := persistence.New()
 	browser := engine.NewBrowser(dataStore)
-	imageCache, err := engine.NewImageCache()
+	imageCache, err := core.NewImageCache()
 	if err != nil {
 		return nil, err
 	}
-	cover := engine.NewCover(dataStore, imageCache)
+	cover := core.NewCover(dataStore, imageCache)
 	nowPlayingRepository := engine.NewNowPlayingRepository()
 	listGenerator := engine.NewListGenerator(dataStore, nowPlayingRepository)
 	users := engine.NewUsers(dataStore)
@@ -53,11 +54,11 @@ func CreateSubsonicAPIRouter() (*subsonic.Router, error) {
 	scrobbler := engine.NewScrobbler(dataStore, nowPlayingRepository)
 	search := engine.NewSearch(dataStore)
 	transcoderTranscoder := transcoder.New()
-	transcodingCache, err := engine.NewTranscodingCache()
+	transcodingCache, err := core.NewTranscodingCache()
 	if err != nil {
 		return nil, err
 	}
-	mediaStreamer := engine.NewMediaStreamer(dataStore, transcoderTranscoder, transcodingCache)
+	mediaStreamer := core.NewMediaStreamer(dataStore, transcoderTranscoder, transcodingCache)
 	players := engine.NewPlayers(dataStore)
 	router := subsonic.New(browser, cover, listGenerator, users, playlists, ratings, scrobbler, search, mediaStreamer, players)
 	return router, nil
@@ -65,4 +66,4 @@ func CreateSubsonicAPIRouter() (*subsonic.Router, error) {
 
 // wire_injectors.go:
 
-var allProviders = wire.NewSet(engine.Set, scanner.New, subsonic.New, app.New, persistence.New)
+var allProviders = wire.NewSet(engine.Set, core.Set, scanner.New, subsonic.New, app.New, persistence.New)
diff --git a/cmd/wire_injectors.go b/cmd/wire_injectors.go
index 1c5499afd..40b209982 100644
--- a/cmd/wire_injectors.go
+++ b/cmd/wire_injectors.go
@@ -3,6 +3,7 @@
 package cmd
 
 import (
+	"github.com/deluan/navidrome/core"
 	"github.com/deluan/navidrome/engine"
 	"github.com/deluan/navidrome/persistence"
 	"github.com/deluan/navidrome/scanner"
@@ -14,6 +15,7 @@ import (
 
 var allProviders = wire.NewSet(
 	engine.Set,
+	core.Set,
 	scanner.New,
 	subsonic.New,
 	app.New,
diff --git a/engine/auth/auth.go b/core/auth/auth.go
similarity index 100%
rename from engine/auth/auth.go
rename to core/auth/auth.go
diff --git a/engine/auth/auth_test.go b/core/auth/auth_test.go
similarity index 97%
rename from engine/auth/auth_test.go
rename to core/auth/auth_test.go
index 621d2556e..fc8f0b796 100644
--- a/engine/auth/auth_test.go
+++ b/core/auth/auth_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/deluan/navidrome/engine/auth"
+	"github.com/deluan/navidrome/core/auth"
 	"github.com/deluan/navidrome/log"
 	"github.com/dgrijalva/jwt-go"
 	. "github.com/onsi/ginkgo"
diff --git a/core/common.go b/core/common.go
new file mode 100644
index 000000000..01ef90b29
--- /dev/null
+++ b/core/common.go
@@ -0,0 +1,15 @@
+package core
+
+import (
+	"context"
+	"github.com/deluan/navidrome/model/request"
+)
+
+func userName(ctx context.Context) string {
+	if user, ok := request.UserFrom(ctx); !ok {
+		return "UNKNOWN"
+	} else {
+		return user.UserName
+	}
+}
+
diff --git a/core/core_suite_test.go b/core/core_suite_test.go
new file mode 100644
index 000000000..b03ee16e5
--- /dev/null
+++ b/core/core_suite_test.go
@@ -0,0 +1,35 @@
+package core
+
+import (
+	"io/ioutil"
+	"os"
+	"testing"
+
+	"github.com/deluan/navidrome/log"
+	"github.com/deluan/navidrome/tests"
+	"github.com/djherbis/fscache"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestEngine(t *testing.T) {
+	tests.Init(t, false)
+	log.SetLevel(log.LevelCritical)
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "Core Suite")
+}
+
+var testCache fscache.Cache
+var testCacheDir string
+
+var _ = Describe("Core Suite Setup", func() {
+	BeforeSuite(func() {
+		testCacheDir, _ = ioutil.TempDir("", "core_test_cache")
+		fs, _ := fscache.NewFs(testCacheDir, 0755)
+		testCache, _ = fscache.NewCache(fs, nil)
+	})
+
+	AfterSuite(func() {
+		os.RemoveAll(testCacheDir)
+	})
+})
diff --git a/engine/cover.go b/core/cover.go
similarity index 99%
rename from engine/cover.go
rename to core/cover.go
index c42216cc1..e121327d2 100644
--- a/engine/cover.go
+++ b/core/cover.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"bytes"
diff --git a/engine/cover_test.go b/core/cover_test.go
similarity index 99%
rename from engine/cover_test.go
rename to core/cover_test.go
index 9bd7f934d..e7a2594e8 100644
--- a/engine/cover_test.go
+++ b/core/cover_test.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"bytes"
diff --git a/engine/file_caches.go b/core/file_caches.go
similarity index 98%
rename from engine/file_caches.go
rename to core/file_caches.go
index 6ff8cbe0f..a8f0f5bfb 100644
--- a/engine/file_caches.go
+++ b/core/file_caches.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"fmt"
diff --git a/engine/file_caches_test.go b/core/file_caches_test.go
similarity index 98%
rename from engine/file_caches_test.go
rename to core/file_caches_test.go
index 3e49e17a2..e5e8e32ee 100644
--- a/engine/file_caches_test.go
+++ b/core/file_caches_test.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"io/ioutil"
diff --git a/engine/media_streamer.go b/core/media_streamer.go
similarity index 98%
rename from engine/media_streamer.go
rename to core/media_streamer.go
index 6ed93e88f..298705810 100644
--- a/engine/media_streamer.go
+++ b/core/media_streamer.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"context"
@@ -10,7 +10,7 @@ import (
 
 	"github.com/deluan/navidrome/conf"
 	"github.com/deluan/navidrome/consts"
-	"github.com/deluan/navidrome/engine/transcoder"
+	"github.com/deluan/navidrome/core/transcoder"
 	"github.com/deluan/navidrome/log"
 	"github.com/deluan/navidrome/model"
 	"github.com/deluan/navidrome/model/request"
diff --git a/engine/media_streamer_test.go b/core/media_streamer_test.go
similarity index 99%
rename from engine/media_streamer_test.go
rename to core/media_streamer_test.go
index 53f8d7e1a..7053ce2e4 100644
--- a/engine/media_streamer_test.go
+++ b/core/media_streamer_test.go
@@ -1,4 +1,4 @@
-package engine
+package core
 
 import (
 	"context"
diff --git a/core/mock_transcoding_repo_test.go b/core/mock_transcoding_repo_test.go
new file mode 100644
index 000000000..6907390c7
--- /dev/null
+++ b/core/mock_transcoding_repo_test.go
@@ -0,0 +1,22 @@
+package core
+
+import "github.com/deluan/navidrome/model"
+
+type mockTranscodingRepository struct {
+	model.TranscodingRepository
+}
+
+func (m *mockTranscodingRepository) Get(id string) (*model.Transcoding, error) {
+	return &model.Transcoding{ID: id, TargetFormat: "mp3", DefaultBitRate: 160}, nil
+}
+
+func (m *mockTranscodingRepository) FindByFormat(format string) (*model.Transcoding, error) {
+	switch format {
+	case "mp3":
+		return &model.Transcoding{ID: "mp31", TargetFormat: "mp3", DefaultBitRate: 160}, nil
+	case "oga":
+		return &model.Transcoding{ID: "oga1", TargetFormat: "oga", DefaultBitRate: 128}, nil
+	default:
+		return nil, model.ErrNotFound
+	}
+}
diff --git a/engine/transcoder/ffmpeg.go b/core/transcoder/ffmpeg.go
similarity index 100%
rename from engine/transcoder/ffmpeg.go
rename to core/transcoder/ffmpeg.go
diff --git a/engine/transcoder/ffmpeg_test.go b/core/transcoder/ffmpeg_test.go
similarity index 100%
rename from engine/transcoder/ffmpeg_test.go
rename to core/transcoder/ffmpeg_test.go
diff --git a/core/wire_providers.go b/core/wire_providers.go
new file mode 100644
index 000000000..f3ae654fb
--- /dev/null
+++ b/core/wire_providers.go
@@ -0,0 +1,14 @@
+package core
+
+import (
+	"github.com/deluan/navidrome/core/transcoder"
+	"github.com/google/wire"
+)
+
+var Set = wire.NewSet(
+	NewCover,
+	NewMediaStreamer,
+	NewTranscodingCache,
+	NewImageCache,
+	transcoder.New,
+)
diff --git a/engine/engine_suite_test.go b/engine/engine_suite_test.go
index 9d7f90f1b..bd2e50649 100644
--- a/engine/engine_suite_test.go
+++ b/engine/engine_suite_test.go
@@ -1,13 +1,10 @@
 package engine
 
 import (
-	"io/ioutil"
-	"os"
 	"testing"
 
 	"github.com/deluan/navidrome/log"
 	"github.com/deluan/navidrome/tests"
-	"github.com/djherbis/fscache"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 )
@@ -18,18 +15,3 @@ func TestEngine(t *testing.T) {
 	RegisterFailHandler(Fail)
 	RunSpecs(t, "Engine Suite")
 }
-
-var testCache fscache.Cache
-var testCacheDir string
-
-var _ = Describe("Engine Suite Setup", func() {
-	BeforeSuite(func() {
-		testCacheDir, _ = ioutil.TempDir("", "engine_test_cache")
-		fs, _ := fscache.NewFs(testCacheDir, 0755)
-		testCache, _ = fscache.NewCache(fs, nil)
-	})
-
-	AfterSuite(func() {
-		os.RemoveAll(testCacheDir)
-	})
-})
diff --git a/engine/users.go b/engine/users.go
index e30fd80b7..a7fe92360 100644
--- a/engine/users.go
+++ b/engine/users.go
@@ -7,7 +7,7 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/deluan/navidrome/engine/auth"
+	"github.com/deluan/navidrome/core/auth"
 	"github.com/deluan/navidrome/model"
 )
 
diff --git a/engine/users_test.go b/engine/users_test.go
index f93f98e14..307287dbe 100644
--- a/engine/users_test.go
+++ b/engine/users_test.go
@@ -3,7 +3,7 @@ package engine
 import (
 	"context"
 
-	"github.com/deluan/navidrome/engine/auth"
+	"github.com/deluan/navidrome/core/auth"
 	"github.com/deluan/navidrome/model"
 	"github.com/deluan/navidrome/persistence"
 	. "github.com/onsi/ginkgo"
diff --git a/engine/wire_providers.go b/engine/wire_providers.go
index 58fd05d40..d2d676588 100644
--- a/engine/wire_providers.go
+++ b/engine/wire_providers.go
@@ -1,13 +1,11 @@
 package engine
 
 import (
-	"github.com/deluan/navidrome/engine/transcoder"
 	"github.com/google/wire"
 )
 
 var Set = wire.NewSet(
 	NewBrowser,
-	NewCover,
 	NewListGenerator,
 	NewPlaylists,
 	NewRatings,
@@ -15,9 +13,5 @@ var Set = wire.NewSet(
 	NewSearch,
 	NewNowPlayingRepository,
 	NewUsers,
-	NewMediaStreamer,
-	transcoder.New,
-	NewTranscodingCache,
-	NewImageCache,
 	NewPlayers,
 )
diff --git a/server/app/app.go b/server/app/app.go
index 5f317ce23..0ad50da87 100644
--- a/server/app/app.go
+++ b/server/app/app.go
@@ -8,7 +8,7 @@ import (
 
 	"github.com/deluan/navidrome/assets"
 	"github.com/deluan/navidrome/conf"
-	"github.com/deluan/navidrome/engine/auth"
+	"github.com/deluan/navidrome/core/auth"
 	"github.com/deluan/navidrome/model"
 	"github.com/deluan/rest"
 	"github.com/go-chi/chi"
diff --git a/server/app/auth.go b/server/app/auth.go
index 16e9f1f72..2fe29accd 100644
--- a/server/app/auth.go
+++ b/server/app/auth.go
@@ -9,7 +9,7 @@ import (
 	"time"
 
 	"github.com/deluan/navidrome/consts"
-	"github.com/deluan/navidrome/engine/auth"
+	"github.com/deluan/navidrome/core/auth"
 	"github.com/deluan/navidrome/log"
 	"github.com/deluan/navidrome/model"
 	"github.com/deluan/navidrome/model/request"
diff --git a/server/subsonic/api.go b/server/subsonic/api.go
index 8ddefd93b..e21de6f27 100644
--- a/server/subsonic/api.go
+++ b/server/subsonic/api.go
@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"encoding/xml"
 	"fmt"
+	"github.com/deluan/navidrome/core"
 	"net/http"
 	"runtime"
 
@@ -22,22 +23,22 @@ type Handler = func(http.ResponseWriter, *http.Request) (*responses.Subsonic, er
 
 type Router struct {
 	Browser       engine.Browser
-	Cover         engine.Cover
+	Cover         core.Cover
 	ListGenerator engine.ListGenerator
 	Playlists     engine.Playlists
 	Ratings       engine.Ratings
 	Scrobbler     engine.Scrobbler
 	Search        engine.Search
 	Users         engine.Users
-	Streamer      engine.MediaStreamer
+	Streamer      core.MediaStreamer
 	Players       engine.Players
 
 	mux http.Handler
 }
 
-func New(browser engine.Browser, cover engine.Cover, listGenerator engine.ListGenerator, users engine.Users,
+func New(browser engine.Browser, cover core.Cover, listGenerator engine.ListGenerator, users engine.Users,
 	playlists engine.Playlists, ratings engine.Ratings, scrobbler engine.Scrobbler, search engine.Search,
-	streamer engine.MediaStreamer, players engine.Players) *Router {
+	streamer core.MediaStreamer, players engine.Players) *Router {
 	r := &Router{Browser: browser, Cover: cover, ListGenerator: listGenerator, Playlists: playlists,
 		Ratings: ratings, Scrobbler: scrobbler, Search: search, Users: users, Streamer: streamer, Players: players}
 	r.mux = r.routes()
diff --git a/server/subsonic/media_retrieval.go b/server/subsonic/media_retrieval.go
index 36a826d1e..c4314ddf4 100644
--- a/server/subsonic/media_retrieval.go
+++ b/server/subsonic/media_retrieval.go
@@ -1,11 +1,11 @@
 package subsonic
 
 import (
+	"github.com/deluan/navidrome/core"
 	"io"
 	"net/http"
 
 	"github.com/deluan/navidrome/consts"
-	"github.com/deluan/navidrome/engine"
 	"github.com/deluan/navidrome/log"
 	"github.com/deluan/navidrome/model"
 	"github.com/deluan/navidrome/resources"
@@ -14,10 +14,10 @@ import (
 )
 
 type MediaRetrievalController struct {
-	cover engine.Cover
+	cover core.Cover
 }
 
-func NewMediaRetrievalController(cover engine.Cover) *MediaRetrievalController {
+func NewMediaRetrievalController(cover core.Cover) *MediaRetrievalController {
 	return &MediaRetrievalController{cover: cover}
 }
 
diff --git a/server/subsonic/stream.go b/server/subsonic/stream.go
index 7c4d4e532..d83d54092 100644
--- a/server/subsonic/stream.go
+++ b/server/subsonic/stream.go
@@ -1,21 +1,21 @@
 package subsonic
 
 import (
+	"github.com/deluan/navidrome/core"
 	"io"
 	"net/http"
 	"strconv"
 
-	"github.com/deluan/navidrome/engine"
 	"github.com/deluan/navidrome/log"
 	"github.com/deluan/navidrome/server/subsonic/responses"
 	"github.com/deluan/navidrome/utils"
 )
 
 type StreamController struct {
-	streamer engine.MediaStreamer
+	streamer core.MediaStreamer
 }
 
-func NewStreamController(streamer engine.MediaStreamer) *StreamController {
+func NewStreamController(streamer core.MediaStreamer) *StreamController {
 	return &StreamController{streamer: streamer}
 }