mirror of
https://github.com/antebudimir/feishin.git
synced 2025-12-31 10:03:33 +00:00
feat: add audio channel configuration for MPV player
- Add audio channels setting (auto/mono/stereo) to MPV properties - Implement UI controls in settings panel and player right controls - Enable immediate MPV property application when setting changes - Update default playback type to LOCAL and sample rate to 48kHz
This commit is contained in:
parent
bf5e7bc774
commit
59e94318bb
6 changed files with 94 additions and 25 deletions
27
README.md
27
README.md
|
|
@ -2,17 +2,21 @@
|
|||
|
||||
# Feishin
|
||||
|
||||
> **⚠️ Fork Notice**: This is a fork of the original [Feishin](https://github.com/jeffvli/feishin) project. I created this fork primarily to add folder view functionality that the original repo wasn't able to accommodate, along with some other features I found useful. While I'll try to keep this fork in sync with the original repo, that's not the primary focus. Feishin was pretty much perfect for me - I just missed the folder view feature. That said, I'll fix any obvious bugs I encounter, but for full support and the most up-to-date version, please stay with the original repository.
|
||||
>
|
||||
> **Note**: I primarily use Linux desktop, so only Linux issues can be addressed if needed.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/jeffvli/feishin/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/jeffvli/feishin?style=flat-square&color=brightgreen"
|
||||
<a href="https://github.com/antebudimir/feishin/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/antebudimir/feishin?style=flat-square&color=brightgreen"
|
||||
alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/jeffvli/feishin/releases">
|
||||
<img src="https://img.shields.io/github/v/release/jeffvli/feishin?style=flat-square&color=blue"
|
||||
<a href="https://github.com/antebudimir/feishin/releases">
|
||||
<img src="https://img.shields.io/github/v/release/antebudimir/feishin?style=flat-square&color=blue"
|
||||
alt="Release">
|
||||
</a>
|
||||
<a href="https://github.com/jeffvli/feishin/releases">
|
||||
<img src="https://img.shields.io/github/downloads/jeffvli/feishin/total?style=flat-square&color=orange"
|
||||
<a href="https://github.com/antebudimir/feishin/releases">
|
||||
<img src="https://img.shields.io/github/downloads/antebudimir/feishin/total?style=flat-square&color=orange"
|
||||
alt="Downloads">
|
||||
</a>
|
||||
</p>
|
||||
|
|
@ -39,17 +43,17 @@ Rewrite of [Sonixd](https://github.com/jeffvli/sonixd).
|
|||
- [x] Scrobble playback to your server
|
||||
- [x] Smart playlist editor (Navidrome)
|
||||
- [x] Synchronized and unsynchronized lyrics support
|
||||
- [ ] [Request a feature](https://github.com/jeffvli/feishin/issues) or [view taskboard](https://github.com/users/jeffvli/projects/5/views/1)
|
||||
- [ ] [Request a feature](https://github.com/antebudimir/feishin/issues) or [view taskboard](https://github.com/users/jeffvli/projects/5/views/1)
|
||||
|
||||
## Screenshots
|
||||
|
||||
<a href="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_full_screen_player.png"><img src="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_full_screen_player.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_album_artist_detail.png"><img src="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_album_artist_detail.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_album_detail.png"><img src="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_album_detail.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_smart_playlist.png"><img src="https://raw.githubusercontent.com/jeffvli/feishin/development/media/preview_smart_playlist.png" width="49.5%"/></a>
|
||||
<a href="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_full_screen_player.png"><img src="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_full_screen_player.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_album_artist_detail.png"><img src="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_album_artist_detail.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_album_detail.png"><img src="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_album_detail.png" width="49.5%"/></a> <a href="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_smart_playlist.png"><img src="https://raw.githubusercontent.com/antebudimir/feishin/development/media/preview_smart_playlist.png" width="49.5%"/></a>
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Desktop (recommended)
|
||||
|
||||
Download the [latest desktop client](https://github.com/jeffvli/feishin/releases). The desktop client is the recommended way to use Feishin. It supports both the MPV and web player backends, as well as includes built-in fetching for lyrics.
|
||||
Download the [latest desktop client](https://github.com/antebudimir/feishin/releases). The desktop client is the recommended way to use Feishin. It supports both the MPV and web player backends, as well as includes built-in fetching for lyrics.
|
||||
|
||||
#### macOS Notes
|
||||
|
||||
|
|
@ -62,18 +66,21 @@ For media keys to work, you will be prompted to allow Feishin to be a Trusted Ac
|
|||
We provide a small install script to download the latest `.AppImage`, make it executable, and also download the icons required by Desktop Environments. Finally, it generates a `.desktop` file to add Feishin to your Application Launcher.
|
||||
|
||||
Simply run the installer like this:
|
||||
|
||||
```sh
|
||||
dir=/your/application/directory
|
||||
curl 'https://raw.githubusercontent.com/jeffvli/feishin/refs/heads/development/install-feishin-appimage' | sh -s -- "$dir"
|
||||
```
|
||||
|
||||
The script also has an option to add launch arguments to run Feishin in native Wayland mode. Note that this is experimental in Electron and therefore not officially supported. If you want to use it, run this instead:
|
||||
|
||||
```sh
|
||||
dir=/your/application/directory
|
||||
curl 'https://raw.githubusercontent.com/jeffvli/feishin/refs/heads/development/install-feishin-appimage' | sh -s -- "$dir" wayland-native
|
||||
```
|
||||
|
||||
It also provides a simple uninstall routine, removing the downloaded files:
|
||||
|
||||
```sh
|
||||
dir=/your/application/directory
|
||||
curl 'https://raw.githubusercontent.com/jeffvli/feishin/refs/heads/development/install-feishin-appimage' | sh -s -- "$dir" remove
|
||||
|
|
@ -165,7 +172,7 @@ chmod 4755 chrome-sandbox
|
|||
sudo chown root:root chrome-sandbox
|
||||
```
|
||||
|
||||
Ubuntu 24.04 specifically introduced breaking changes that affect how namespaces work. Please see https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#:~:text=security%20improvements%20 for possible fixes.
|
||||
Ubuntu 24.04 specifically introduced breaking changes that affect how namespaces work. Please see <https://discourse.ubuntu.com/t/ubuntu-24-04-lts-noble-numbat-release-notes/39890#:~:text=security%20improvements%20> for possible fixes.
|
||||
|
||||
## Development
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ linux:
|
|||
npmRebuild: false
|
||||
publish:
|
||||
provider: github
|
||||
owner: jeffvli
|
||||
owner: antebudimir
|
||||
repo: feishin
|
||||
channel: latest
|
||||
releaseType: draft
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "feishin",
|
||||
"version": "0.24.0",
|
||||
"version": "0.25.0-fork",
|
||||
"description": "A modern self-hosted music player.",
|
||||
"keywords": [
|
||||
"subsonic",
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import { PlaybackType } from '/@/shared/types/types';
|
|||
|
||||
const ipc = isElectron() ? window.api.ipc : null;
|
||||
const remote = isElectron() ? window.api.remote : null;
|
||||
const mpvPlayer = isElectron() ? window.api.mpvPlayer : null;
|
||||
|
||||
export const RightControls = () => {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -218,6 +219,46 @@ export const RightControls = () => {
|
|||
)}
|
||||
</Group>
|
||||
<Group align="center" gap="xs" wrap="nowrap">
|
||||
{(playbackType === PlaybackType.LOCAL || playbackType === PlaybackType.WEB) && (
|
||||
<ActionIcon
|
||||
icon={
|
||||
playbackSettings.mpvProperties.audioChannels === 'mono'
|
||||
? 'volumeNormal'
|
||||
: 'volumeMax'
|
||||
}
|
||||
iconProps={{
|
||||
size: 'lg',
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
const current =
|
||||
playbackSettings.mpvProperties.audioChannels || 'stereo';
|
||||
const next = current === 'mono' ? 'stereo' : 'mono';
|
||||
setSettings({
|
||||
playback: {
|
||||
...playbackSettings,
|
||||
mpvProperties: {
|
||||
...playbackSettings.mpvProperties,
|
||||
audioChannels: next,
|
||||
},
|
||||
},
|
||||
});
|
||||
// Apply to MPV immediately
|
||||
mpvPlayer?.setProperties({
|
||||
'audio-channels': next,
|
||||
});
|
||||
}}
|
||||
size="sm"
|
||||
tooltip={{
|
||||
label:
|
||||
playbackType === PlaybackType.WEB
|
||||
? `Audio: ${playbackSettings.mpvProperties.audioChannels || 'stereo'} (MPV only)`
|
||||
: `Audio: ${playbackSettings.mpvProperties.audioChannels || 'stereo'}`,
|
||||
openDelay: 0,
|
||||
}}
|
||||
variant="subtle"
|
||||
/>
|
||||
)}
|
||||
<DropdownMenu arrowOffset={12} offset={0} position="top-end" width={425} withArrow>
|
||||
<DropdownMenu.Target>
|
||||
<ActionIcon
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ export const getMpvSetting = (
|
|||
value: any,
|
||||
) => {
|
||||
switch (key) {
|
||||
case 'audioChannels':
|
||||
return { 'audio-channels': value };
|
||||
case 'audioExclusiveMode':
|
||||
return { 'audio-exclusive': value || 'no' };
|
||||
case 'audioSampleRateHz':
|
||||
|
|
@ -53,6 +55,7 @@ export const getMpvSetting = (
|
|||
|
||||
export const getMpvProperties = (settings: SettingsState['playback']['mpvProperties']) => {
|
||||
const properties: Record<string, any> = {
|
||||
'audio-channels': settings.audioChannels || 'stereo',
|
||||
'audio-exclusive': settings.audioExclusiveMode || 'no',
|
||||
'audio-samplerate':
|
||||
settings.audioSampleRateHz === 0 ? undefined : settings.audioSampleRateHz,
|
||||
|
|
@ -271,6 +274,22 @@ export const MpvSettings = () => {
|
|||
isHidden: settings.type !== PlaybackType.LOCAL,
|
||||
title: t('setting.gaplessAudio', { postProcess: 'sentenceCase' }),
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<Select
|
||||
data={[
|
||||
{ label: 'Mono', value: 'mono' },
|
||||
{ label: 'Stereo', value: 'stereo' },
|
||||
]}
|
||||
defaultValue={settings.mpvProperties.audioChannels || 'stereo'}
|
||||
onChange={(e) => handleSetMpvProperty('audioChannels', e)}
|
||||
/>
|
||||
),
|
||||
description:
|
||||
'Select the audio channel mode. Stereo is the default, mono downmixes to a single channel.',
|
||||
isHidden: settings.type !== PlaybackType.LOCAL,
|
||||
title: 'Audio Channels',
|
||||
},
|
||||
{
|
||||
control: (
|
||||
<NumberInput
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ const TranscodingConfigSchema = z.object({
|
|||
});
|
||||
|
||||
const MpvSettingsSchema = z.object({
|
||||
audioChannels: z.enum(['mono', 'stereo']).optional(),
|
||||
audioExclusiveMode: z.enum(['no', 'yes']),
|
||||
audioFormat: z.enum(['float', 's16', 's32']).optional(),
|
||||
audioSampleRateHz: z.number().optional(),
|
||||
|
|
@ -657,9 +658,10 @@ const initialState: SettingsState = {
|
|||
mediaSession: false,
|
||||
mpvExtraParameters: [],
|
||||
mpvProperties: {
|
||||
audioChannels: 'stereo',
|
||||
audioExclusiveMode: 'no',
|
||||
audioFormat: undefined,
|
||||
audioSampleRateHz: 0,
|
||||
audioSampleRateHz: 48000,
|
||||
gaplessAudio: 'weak',
|
||||
replayGainClip: true,
|
||||
replayGainFallbackDB: undefined,
|
||||
|
|
@ -678,7 +680,7 @@ const initialState: SettingsState = {
|
|||
transcode: {
|
||||
enabled: false,
|
||||
},
|
||||
type: PlaybackType.WEB,
|
||||
type: PlaybackType.LOCAL,
|
||||
webAudio: true,
|
||||
},
|
||||
remote: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue