Skip to content

Commit

Permalink
add suno extend (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyf-github-user authored Aug 12, 2024
1 parent c1081d4 commit b46a96e
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "add suno extend",
"packageName": "@acedatacloud/nexior",
"email": "[email protected]",
"dependentChangeType": "patch"
}
9 changes: 8 additions & 1 deletion src/components/suno/ConfigPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
<lyric-input v-if="config?.custom && !config.instrumental" class="mb-4" />
<style-input v-if="config?.custom" class="mb-4" />
<title-input v-if="config?.custom" class="mb-4" />
<extend-from-input v-if="config?.action === 'extend'" class="mb-4" />
<div class="actions">
<el-button type="primary" class="btn w-full" round @click="onGenerate">
<el-button v-if="config?.action !== 'extend'" type="primary" class="btn w-full" round @click="onGenerate">
<font-awesome-icon icon="fa-solid fa-magic" class="mr-2" />
{{ $t('suno.button.generate') }}
</el-button>
<el-button v-else type="primary" class="btn w-full" round @click="onGenerate">
<font-awesome-icon icon="fa-solid fa-magic" class="mr-2" />
{{ $t('suno.button.extend') }}
</el-button>
</div>
</div>
</div>
Expand All @@ -25,6 +30,7 @@ import PromptInput from './config/PromptInput.vue';
import LyricInput from './config/LyricInput.vue';
import StyleInput from './config/StyleInput.vue';
import TitleInput from './config/TitleInput.vue';
import ExtendFromInput from './config/ExtendFromInput.vue';
import InstrumentSwitch from './config/InstrumentSwitch.vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
Expand All @@ -37,6 +43,7 @@ export default defineComponent({
InstrumentSwitch,
StyleInput,
TitleInput,
ExtendFromInput,
FontAwesomeIcon,
ElButton
},
Expand Down
159 changes: 159 additions & 0 deletions src/components/suno/config/ExtendFromInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<template>
<div class="field">
<div class="box">
<h2 class="title">{{ $t('suno.name.extend') }}</h2>
<div class="input-wrapper">
<el-input-number
v-model="value"
class="value"
:min="0"
:max="audio?.duration"
:controls="false"
:placeholder="$t('suno.placeholder.extend.continue_at')"
@change="handleChange"
/>
</div>
</div>
<div class="task">
<div class="audio" @click="onClick(audio)">
<div v-loading="!audio?.audio_url || !audio?.video_url" class="left">
<el-image :src="audio?.image_url" class="cover" fit="cover" />
<div
v-if="
audio?.audio_url &&
$store.state?.suno?.audio?.id === audio.id &&
$store.state?.suno?.audio?.state === 'playing'
"
class="overlay"
@click="onPause(audio)"
>
<el-icon><video-pause /></el-icon>
</div>
<div
v-if="
audio?.audio_url &&
($store.state?.suno?.audio?.id !== audio.id ||
($store.state?.suno?.audio?.id === audio.id && $store.state?.suno?.audio?.state === 'paused'))
"
class="overlay"
@click="onPlay(audio)"
>
<el-icon><video-play /></el-icon>
</div>
<div v-if="audio?.duration" class="duration">
{{ useFormatDuring(audio?.duration) }}
</div>
</div>
<div class="info">
<h2 class="title">{{ audio?.title }}</h2>
<p class="style">{{ audio?.style }}</p>
</div>
</div>
</div>
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { useFormatDuring } from '@/utils/number';
import { ISunoAudio } from '@/models';
import { ElImage, ElIcon, ElInputNumber } from 'element-plus';
import { VideoPlay, VideoPause } from '@element-plus/icons-vue';
export const DEFAULT_LYRIC = '';
export default defineComponent({
name: 'ExtendFromInput',
components: {
ElImage,
ElIcon,
ElInputNumber,
VideoPlay,
VideoPause
},
data() {
return {};
},
computed: {
// @ts-ignore
audio() {
// @ts-ignore
return this.$store.state.suno?.config?.audio;
},
value: {
get() {
return this.$store.state.suno?.config?.continue_at;
},
set(val: string) {
console.debug('set continue_at', val);
this.$store.commit('suno/setConfig', {
...this.$store.state.suno?.config,
continue_at: val ? parseInt(val) : undefined
});
}
}
},
mounted() {
if (!this.value) {
this.value = undefined;
}
},
methods: {
handleChange(val: number) {
if (val < 0) {
this.value = 0;
// @ts-ignore
} else if (val > this.audio?.duration) {
this.value = this.audio?.duration;
} else {
this.value = val;
}
},
useFormatDuring,
onPlay(audio: ISunoAudio) {
this.$store.dispatch('suno/setAudio', {
...this.$store.state.suno.audio,
...audio,
state: 'playing'
});
console.log('on play');
},
onPause(audio: ISunoAudio) {
this.$store.dispatch('suno/setAudio', {
...this.$store.state.suno.audio,
...audio,
state: 'paused'
});
console.log('on pause');
},
onClick(audio: ISunoAudio) {
if (this.$store.state?.suno?.audio?.id !== audio.id) {
this.onPlay({
...audio,
progress: 0
});
}
}
}
});
</script>

<style lang="scss" scoped>
.field {
.box {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between; // 添加这行
position: relative;
.title {
font-size: 14px;
margin-bottom: 10px;
}
.input-wrapper {
width: 150px; // 根据需要调整宽度
margin-left: 30px; // 增加左边距
}
}
}
</style>
11 changes: 11 additions & 0 deletions src/components/suno/config/LyricInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<info-icon :content="$t('suno.description.lyrics')" class="info" />
</div>
<el-input
v-if="config?.action !== 'extend'"
v-model="lyric"
:rows="3"
type="textarea"
Expand All @@ -13,6 +14,16 @@
:maxlength="3000"
show-word-limit
/>
<el-input
v-else
v-model="lyric"
:rows="3"
type="textarea"
class="lyrics"
:placeholder="$t('suno.placeholder.extend.lyrics')"
:maxlength="3000"
show-word-limit
/>
</div>
</template>

Expand Down
29 changes: 26 additions & 3 deletions src/components/suno/task/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<p class="style">{{ audio?.style }}</p>
</div>
<div class="right">
<el-button size="small" round @click="onExtend($event, audio)">{{ $t('suno.button.extend') }}</el-button>
<el-tooltip effect="dark" :content="$t('suno.button.download')" placement="top">
<font-awesome-icon
v-if="audio?.audio_url"
Expand All @@ -59,7 +60,7 @@
import { defineComponent } from 'vue';
import { useFormatDuring } from '@/utils/number';
import { ISunoAudio, ISunoTask } from '@/models';
import { ElImage, ElIcon, ElTooltip } from 'element-plus';
import { ElImage, ElIcon, ElTooltip, ElButton } from 'element-plus';
import { VideoPlay, VideoPause } from '@element-plus/icons-vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
Expand All @@ -69,6 +70,7 @@ export default defineComponent({
ElImage,
ElIcon,
ElTooltip,
ElButton,
FontAwesomeIcon,
VideoPlay,
VideoPause
Expand Down Expand Up @@ -130,6 +132,23 @@ export default defineComponent({
});
}
},
onExtend(event: MouseEvent, audio: ISunoAudio) {
event.stopPropagation();
console.log('on extend');
// download url here
console.debug('set config', audio);
this.$store.commit('suno/setConfig', {
...this.$store.state.suno?.config,
model: audio.model,
custom: true,
instrumental: false,
style: audio.style,
action: 'extend',
audio: audio,
audio_id: audio.id,
continue_at: audio.duration
});
},
onDownload(event: MouseEvent, audioUrl: string) {
event.stopPropagation();
console.log('on download');
Expand Down Expand Up @@ -223,16 +242,20 @@ export default defineComponent({
}
}
.right {
width: 60px;
width: 120px;
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-end;
padding-right: 1px;
.icon {
display: block;
z-index: 100;
cursor: pointer;
margin-right: 15px;
}
.el-button {
margin-right: 15px; /* Add margin to the right of the button */
}
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/i18n/zh-CN/suno.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"button.extend": {
"message": "继续生成",
"description": "继续生成按钮文本"
},
"button.download": {
"message": "下载",
"description": "下载按钮文本"
Expand Down Expand Up @@ -35,6 +39,10 @@
"message": "歌曲描述",
"description": "内容输入的提示"
},
"name.extend": {
"message": "扩展歌曲来自",
"description": "内容输入的提示"
},
"name.lyrics": {
"message": "歌词内容",
"description": "歌词内容输入的提示"
Expand Down Expand Up @@ -91,6 +99,14 @@
"message": "请输入歌词...",
"description": "填充级别的占位符"
},
"placeholder.extend.lyrics": {
"message": "请输入需要扩展的歌词...",
"description": "填充级别的占位符"
},
"placeholder.extend.continue_at": {
"message": "请输入需要从歌曲哪秒进行扩展...",
"description": "填充级别的占位符"
},
"placeholder.style": {
"message": "请输入要生成的歌曲风格的提示词,例如 acoustic pop",
"description": "提示字段中的占位文本"
Expand Down
3 changes: 3 additions & 0 deletions src/models/suno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export interface ISunoConfig {
title?: string;
style?: string;
action?: string;
audio?: ISunoAudio | undefined;
audio_id?: string;
continue_at: number;
}
export interface ISunoAudioRequest {
action?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/store/suno/models.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IApplication, ICredential, IService, ISunoAudio, Status } from '@/models';
import { ISunoConfig, ISunoTask, Song } from '@/models';
import { ISunoConfig, ISunoTask } from '@/models';

export interface ISunoState {
application: IApplication | undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/store/suno/persist.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export default ['suno.config', 'suno.credential', 'suno.application', 'suno.tasks'];
export default ['suno.credential', 'suno.application', 'suno.tasks'];
2 changes: 1 addition & 1 deletion src/store/suno/state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ISunoState } from './models';
import { Status, Song } from '@/models';
import { Status } from '@/models';

export default (): ISunoState => {
return {
Expand Down

0 comments on commit b46a96e

Please sign in to comment.