Skip to content

Commit

Permalink
chore: bump dependencies, added script to download live2d sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
nekomeowww committed Dec 2, 2024
1 parent 72f41d8 commit 330c6c0
Show file tree
Hide file tree
Showing 20 changed files with 4,549 additions and 4,981 deletions.
81 changes: 9 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,80 +1,17 @@
<p align="center">
<img src="https://user-images.githubusercontent.com/11247099/140462375-7b7ac4db-35b7-453c-8a05-13d8d20282c4.png" width="600"/>
</p>

<h2 align="center">
<a href="https://github.com/antfu/vitesse">Vitesse</a> for Nuxt 3
</h2><br>
<h1 align="center">アイリ VTuber</h1>

<p align="center">
<br>
<a href="https://vitesse-nuxt3.netlify.app/">🖥 Online Preview</a>
<br><br>
<a href="https://stackblitz.com/github/antfu/vitesse-nuxt3"><img src="https://developer.stackblitz.com/img/open_in_stackblitz.svg" alt=""></a>
[<a href="https://airi.ayaka.io">Try it</a>]
</p>

## Features

- 💚 [Nuxt 3](https://nuxt.com/) - SSR, ESR, File-based routing, components auto importing, modules, etc.

- ⚡️ Vite - Instant HMR.

- 🎨 [UnoCSS](https://github.com/unocss/unocss) - The instant on-demand atomic CSS engine.

- 😃 Use icons from any icon sets in Pure CSS, powered by [UnoCSS](https://github.com/unocss/unocss).

- 🔥 The `<script setup>` syntax.

- 🍍 [State Management via Pinia](https://github.com/vuejs/pinia), see [./composables/user.ts](./composables/user.ts).

- 📑 [Layout system](./layouts).

- 📥 APIs auto importing - for Composition API, VueUse and custom composables.

- 🏎 Zero-config cloud functions and deploy.

- 🦾 TypeScript, of course.

- 📲 [PWA](https://github.com/vite-pwa/nuxt) with offline support and auto-update behavior.
> Heavily inspired by [Neuro-sama](https://www.youtube.com/@Neurosama)
## Plugins
## Development

### Nuxt Modules

- [VueUse](https://github.com/vueuse/vueuse) - collection of useful composition APIs.
- [ColorMode](https://github.com/nuxt-modules/color-mode) - dark and Light mode with auto detection made easy with Nuxt.
- [UnoCSS](https://github.com/unocss/unocss) - the instant on-demand atomic CSS engine.
- [Pinia](https://github.com/vuejs/pinia) - intuitive, type safe, light and flexible Store for Vue.
- [VitePWA](https://github.com/vite-pwa/nuxt) - zero-config PWA Plugin for Nuxt 3.
- [DevTools](https://github.com/nuxt/devtools) - unleash Nuxt Developer Experience.

## IDE

We recommend using [VS Code](https://code.visualstudio.com/) with [Volar](https://github.com/johnsoncodehk/volar) to get the best experience (You might want to disable [Vetur](https://vuejs.github.io/vetur/) if you have it).

## Variations

- [vitesse](https://github.com/antfu/vitesse) - Opinionated Vite Starter Template
- [vitesse-lite](https://github.com/antfu/vitesse-lite) - Lightweight version of Vitesse
- [vitesse-nuxt-bridge](https://github.com/antfu/vitesse-nuxt-bridge) - Vitesse for Nuxt 2 with Bridge
- [vitesse-webext](https://github.com/antfu/vitesse-webext) - WebExtension Vite starter template

## Try it now!

### Online

<a href="https://stackblitz.com/github/antfu/vitesse-nuxt3"><img src="https://developer.stackblitz.com/img/open_in_stackblitz.svg" alt=""></a>

### GitHub Template

[Create a repo from this template on GitHub](https://github.com/antfu/vitesse-nuxt3/generate).

### Clone to local

If you prefer to do it manually with the cleaner git history
```shell
pnpm i
```

```bash
npx degit antfu/vitesse-nuxt3 my-nuxt3-app
cd my-nuxt3-app
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm
```shell
pnpm dev
```
2 changes: 1 addition & 1 deletion components/AudioWaveform.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useElementBounding } from '@vueuse/core'
import { onMounted, ref } from 'vue'
const containerRef = ref<HTMLDivElement>()
// https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode
Expand Down
4 changes: 2 additions & 2 deletions components/Live2DViewer.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts" generic="T extends any, O extends any">
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { Application } from '@pixi/app'
import { extensions } from '@pixi/extensions'
import { Ticker, TickerPlugin } from '@pixi/ticker'
import { Live2DModel, MotionPreloadStrategy, MotionPriority } from 'pixi-live2d-display/cubism4'
import { useElementBounding, useWindowSize } from '@vueuse/core'
import { Live2DModel, MotionPreloadStrategy, MotionPriority } from 'pixi-live2d-display/cubism4'
import { onMounted, onUnmounted, ref, watch } from 'vue'
const props = withDefaults(defineProps<{
model: string
Expand Down
22 changes: 11 additions & 11 deletions components/MainStage.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useLocalStorage } from '@vueuse/core'
import type {
CoreAssistantMessage,
CoreSystemMessage,
CoreUserMessage,
} from 'ai'
import { llmInferenceEndToken } from '../constants'
import type {
Emotion,
} from '../constants/emotions'
import {
EMOTION_EmotioMotionName_value,
EmotionThinkMotionName,
} from '../constants/emotions'
import { useLocalStorage } from '@vueuse/core'
import { computed, onMounted, ref, watch } from 'vue'
import Avatar from '../assets/live2d/models/hiyori_free_zh/avatar.png'
import { useLLM } from '../stores/llm'
import { useMarkdown } from '../composables/markdown'
import { useQueue } from '../composables/queue'
import {
useDelayMessageQueue,
useEmotionsMessageQueue,
useMessageContentQueue,
} from '../composables/queues'
import { useMarkdown } from '../composables/markdown'
import { llmInferenceEndToken } from '../constants'
import {
EMOTION_EmotioMotionName_value,
EmotionThinkMotionName,
} from '../constants/emotions'
import SystemPromptV2 from '../constants/prompts/system-v2'
import { useLLM } from '../stores/llm'
import BasicTextarea from './BasicTextarea.vue'
// import AudioWaveform from './AudioWaveform.vue'
import Live2DViewer from './Live2DViewer.vue'
import BasicTextarea from './BasicTextarea.vue'
const nowSpeakingAvatarBorderOpacityMin = 30
const nowSpeakingAvatarBorderOpacityMax = 100
Expand Down
6 changes: 3 additions & 3 deletions composables/markdown.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { unified } from 'unified'
import RemarkRehype from 'remark-rehype'
import RemarkParse from 'remark-parse'
import RehypeStringify from 'rehype-stringify'
import RemarkParse from 'remark-parse'
import RemarkRehype from 'remark-rehype'
import { unified } from 'unified'

export function useMarkdown() {
const instance = unified()
Expand Down
2 changes: 1 addition & 1 deletion composables/queue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ref } from 'vue'
import type { Ref } from 'vue'
import { ref } from 'vue'

export interface HandlerContext<T> {
data: T
Expand Down
8 changes: 4 additions & 4 deletions composables/queues.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Emotion } from '../constants/emotions'
import { ref } from 'vue'

import { llmInferenceEndToken } from '../constants'
import type { Emotion } from '../constants/emotions'
import { EMOTION_VALUES } from '../constants/emotions'
import { useQueue } from './queue'

Expand Down Expand Up @@ -100,7 +100,7 @@ export function useEmotionsMessageQueue(emotionsQueue: ReturnType<typeof useQueu
export function useDelayMessageQueue(useEmotionsMessageQueue: ReturnType<typeof useQueue<string>>) {
function splitDelays(content: string) {
// doesn't include the emotion, continue
if (!(/<\|DELAY:(\d+)\|>/gi.test(content))) {
if (!(/<\|DELAY:\d+\|>/i.test(content))) {
return {
ok: false,
delay: 0,
Expand All @@ -109,7 +109,7 @@ export function useDelayMessageQueue(useEmotionsMessageQueue: ReturnType<typeof
}
}

const delayExecArray = /<\|DELAY:(\d+)\|>/gi.exec(content)
const delayExecArray = /<\|DELAY:(\d+)\|>/i.exec(content)

const delay = delayExecArray?.[1]
if (!delay) {
Expand Down Expand Up @@ -214,7 +214,7 @@ export function useMessageContentQueue(ttsQueue: ReturnType<typeof useQueue<stri
return
}

const endMarker = /(\.)|(\?)|(!)/
const endMarker = /[.?!]/
processed.value += ctx.data

while (processed.value) {
Expand Down
10 changes: 8 additions & 2 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
version: '0.2'
version: "0.2"
ignorePaths: []
dictionaryDefinitions: []
dictionaries: []
words:
- airi-vtuber
- composables
- elevenlabs
- hiyori
- iconify
- Myriam
- nekomeowww
- Neuro
- nuxi
- nuxt
- nuxtjs
- ofetch
- openai
- pinia
- pixi
- rehype
- unocss
- vueuse
- airi-vtuber
- Neuro-sama
ignoreWords: []
import: []
5 changes: 5 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export default nuxt(
{
unocss: true,
formatters: true,
yaml: false,
markdown: false,
ignores: [
'public/assets/**/*',
],
},
),
)
35 changes: 34 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Buffer } from 'node:buffer'
import { mkdir } from 'node:fs/promises'
import { join } from 'node:path'
import { ofetch } from 'ofetch'

import { appDescription } from './constants/index'
import { exists } from './scripts/fs'
import { unzip } from './scripts/unzip'

export default defineNuxtConfig({
modules: [
Expand All @@ -9,8 +16,10 @@ export default defineNuxtConfig({
'@nuxt/eslint',
],

ssr: false,

experimental: {
// when using generate, payload js assets included in sw precache manifest
// when using generate, payload js assets included in sw pre-cache manifest
// but missing on offline, disabling extraction it until fixed
payloadExtraction: false,
renderJsonPayloads: true,
Expand Down Expand Up @@ -71,9 +80,33 @@ export default defineNuxtConfig({
inlineStyles: false,
},

vite: {
plugins: [
{
name: 'live2d-cubism',
async configResolved(config) {
if (await exists(join(config.root, 'public/assets/js/CubismSdkForWeb-5-r.1'))) {
return
}

console.log('Downloading Cubism SDK...')
const stream = await ofetch('https://dist.ayaka.moe/npm/live2d-cubism/CubismSdkForWeb-5-r.1.zip', { responseType: 'arrayBuffer' })

console.log('Unzipping Cubism SDK...')
await mkdir(join(config.root, 'public/assets/js'), { recursive: true })
await unzip(Buffer.from(stream), join(config.root, 'public/assets/js'))

console.log('Cubism SDK downloaded and unzipped.')
},
},
],
},

eslint: {
config: {
standalone: false,
},
},

compatibilityDate: '2024-12-02',
})
69 changes: 36 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"type": "module",
"private": true,
"packageManager": "pnpm@9.1.0",
"packageManager": "pnpm@9.14.4",
"scripts": {
"build": "nuxi build",
"dev:pwa": "VITE_PLUGIN_PWA=true nuxi dev",
Expand All @@ -11,43 +11,46 @@
"start": "node .output/server/index.mjs",
"start:generate": "npx serve .output/public",
"lint": "eslint .",
"lint:fix": "eslint --fix .",
"typecheck": "vue-tsc --noEmit"
},
"devDependencies": {
"@antfu/eslint-config": "^2.17.0",
"@iconify-json/carbon": "^1.1.32",
"@iconify-json/twemoji": "^1.1.15",
"@nuxt/devtools": "^1.3.1",
"@nuxt/eslint": "^0.3.12",
"@nuxtjs/color-mode": "^3.4.1",
"@pinia/nuxt": "^0.5.1",
"@unocss/eslint-config": "^0.60.0",
"@unocss/nuxt": "^0.60.0",
"@vueuse/nuxt": "^10.9.0",
"consola": "^3.2.3",
"eslint": "^8.57.0",
"eslint-plugin-format": "^0.1.1",
"nuxt": "^3.11.2",
"pinia": "^2.1.7",
"typescript": "^5.4.5",
"vue-tsc": "^2.0.17"
},
"dependencies": {
"@ai-sdk/openai": "^0.0.24",
"@pixi/app": "6",
"@pixi/extensions": "6",
"@pixi/interaction": "6",
"@pixi/ticker": "6",
"@vueuse/components": "^10.11.0",
"ai": "^3.1.30",
"elevenlabs": "^0.6.0",
"ofetch": "^1.3.4",
"openai": "^4.49.0",
"@ai-sdk/openai": "^1.0.5",
"@pixi/app": "^6.5.10",
"@pixi/extensions": "^6.5.10",
"@pixi/interaction": "^6.5.10",
"@pixi/ticker": "^6.5.10",
"@vueuse/components": "^12.0.0",
"ai": "^4.0.9",
"elevenlabs": "^0.18.1",
"ofetch": "^1.4.1",
"openai": "^4.73.1",
"pixi-live2d-display": "^0.4.0",
"rehype-stringify": "^10.0.0",
"rehype-stringify": "^10.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.0",
"unified": "^11.0.4",
"remark-rehype": "^11.1.1",
"unified": "^11.0.5",
"zod": "^3.23.8"
},
"devDependencies": {
"@antfu/eslint-config": "^3.11.2",
"@iconify-json/carbon": "^1.2.4",
"@iconify-json/twemoji": "^1.2.1",
"@nuxt/devtools": "^1.6.1",
"@nuxt/eslint": "^0.7.2",
"@nuxtjs/color-mode": "^3.5.2",
"@pinia/nuxt": "^0.8.0",
"@types/yauzl": "^2.10.3",
"@unocss/eslint-config": "^0.65.0-beta.3",
"@unocss/nuxt": "^0.65.0-beta.3",
"@vueuse/nuxt": "^12.0.0",
"consola": "^3.2.3",
"eslint": "^9.16.0",
"eslint-plugin-format": "^0.1.3",
"nuxt": "^3.14.1592",
"pinia": "^2.2.8",
"typescript": "^5.7.2",
"vue-tsc": "^2.1.10",
"yauzl": "^3.2.0"
}
}
Loading

0 comments on commit 330c6c0

Please sign in to comment.