live2d -> talkinghead name change
26
README.md
@@ -138,7 +138,7 @@ cd SillyTavern-extras
|
||||
| `edge-tts` | [Microsoft Edge TTS client](https://github.com/rany2/edge-tts) | ✔️ Yes |
|
||||
| `coqui-tts` | [Coqui TTS server](https://github.com/coqui-ai/TTS) | :x: No |
|
||||
| `chromadb` | Infinity context server | :x: No |
|
||||
| `live2d` | Talking Head Sprites | :x: No |
|
||||
| `talkinghead` | Talking Head Sprites | :x: No |
|
||||
|
||||
## Additional options
|
||||
| Flag | Description |
|
||||
@@ -152,7 +152,7 @@ cd SillyTavern-extras
|
||||
| `--mps` or `--m1` | Run the models on Apple Silicon. Only for M1 and M2 processors. |
|
||||
| `--cuda` | Uses CUDA (GPU+VRAM) to run modules if it is available. Otherwise, falls back to using CPU. |
|
||||
| `--cuda-device` | Specifies a CUDA device to use. Defaults to `cuda:0` (first available GPU). |
|
||||
| `--live2d-gpu` | Uses GPU for live2d (10x FPS increase in animation). |
|
||||
| `--talkinghead-gpu` | Uses GPU for talkinghead (10x FPS increase in animation). |
|
||||
| `--coqui-gpu` | Uses GPU for coqui TTS (if available). |
|
||||
| `--coqui-model` | If provided, downloads and preloads a coqui TTS model. Default: none.<br>Example: `tts_models/multilingual/multi-dataset/bark` |
|
||||
| `--summarization-model` | Load a custom summarization model.<br>Expects a HuggingFace model ID.<br>Default: [Qiliang/bart-large-cnn-samsum-ChatGPT_v3](https://huggingface.co/Qiliang/bart-large-cnn-samsum-ChatGPT_v3) |
|
||||
@@ -512,31 +512,31 @@ _progress (string, Optional): Show progress bar in terminal.
|
||||
#### **Output**
|
||||
MP3 audio file.
|
||||
|
||||
### Loads a Live2D character by specifying the character's image URL.
|
||||
`GET /api/live2d/load`
|
||||
### Loads a talkinghead character by specifying the character's image URL.
|
||||
`GET /api/talkinghead/load`
|
||||
#### **Parameters**
|
||||
loadchar (string, required): The URL of the character's image. The URL should point to a PNG image.
|
||||
{ "loadchar": "http://localhost:8000/characters/Aqua.png" }
|
||||
#### **Example**
|
||||
'http://localhost:5100/api/live2d/load?loadchar=http://localhost:8000/characters/Aqua.png'
|
||||
'http://localhost:5100/api/talkinghead/load?loadchar=http://localhost:8000/characters/Aqua.png'
|
||||
#### **Output**
|
||||
'OK'
|
||||
|
||||
### Animates the live2d sprite to start talking.
|
||||
`GET /api/live2d/start_talking`
|
||||
### Animates the talkinghead sprite to start talking.
|
||||
`GET /api/talkinghead/start_talking`
|
||||
#### **Example**
|
||||
'http://localhost:5100/api/live2d/start_talking'
|
||||
'http://localhost:5100/api/talkinghead/start_talking'
|
||||
#### **Output**
|
||||
"started"
|
||||
|
||||
### Animates the live2d sprite to stop talking.
|
||||
`GET /api/live2d/stop_talking`
|
||||
### Animates the talkinghead sprite to stop talking.
|
||||
`GET /api/talkinghead/stop_talking`
|
||||
#### **Example**
|
||||
'http://localhost:5100/api/live2d/stop_talking'
|
||||
'http://localhost:5100/api/talkinghead/stop_talking'
|
||||
#### **Output**
|
||||
"stopped"
|
||||
|
||||
### Outputs the animated live2d sprite.
|
||||
`GET /api/live2d/result_feed`
|
||||
### Outputs the animated talkinghead sprite.
|
||||
`GET /api/talkinghead/result_feed`
|
||||
#### **Output**
|
||||
Animated transparent image
|
||||
|
||||
58
server.py
@@ -86,7 +86,7 @@ parser.add_argument('--chroma-persist', help="ChromaDB persistence", default=Tru
|
||||
parser.add_argument(
|
||||
"--secure", action="store_true", help="Enforces the use of an API key"
|
||||
)
|
||||
parser.add_argument("--live2d-gpu", action="store_true", help="Run the live2d animation on the GPU (CPU is default)")
|
||||
parser.add_argument("--talkinghead-gpu", action="store_true", help="Run the talkinghead animation on the GPU (CPU is default)")
|
||||
parser.add_argument("--coqui-gpu", action="store_false", help="Run the voice models on the GPU (CPU is default)")
|
||||
parser.add_argument("--coqui-model", help="Load a custom Coqui TTS model")
|
||||
parser.add_argument("--stt-vosk-model-path", help="Load a custom vosk speech-to-text model")
|
||||
@@ -175,27 +175,27 @@ if not torch.cuda.is_available() and not args.cpu:
|
||||
|
||||
print(f"{Fore.GREEN}{Style.BRIGHT}Using torch device: {device_string}{Style.RESET_ALL}")
|
||||
|
||||
if "live2d" in modules:
|
||||
if "talkinghead" in modules:
|
||||
import sys
|
||||
import threading
|
||||
mode = "cuda" if args.live2d_gpu else "cpu"
|
||||
print("Initializing live2d pipeline in " + mode + " mode....")
|
||||
live2d_path = os.path.abspath(os.path.join(os.getcwd(), "live2d"))
|
||||
sys.path.append(live2d_path) # Add the path to the 'tha3' module to the sys.path list
|
||||
mode = "cuda" if args.talkinghead_gpu else "cpu"
|
||||
print("Initializing talkinghead pipeline in " + mode + " mode....")
|
||||
talkinghead_path = os.path.abspath(os.path.join(os.getcwd(), "talkinghead"))
|
||||
sys.path.append(talkinghead_path) # Add the path to the 'tha3' module to the sys.path list
|
||||
|
||||
try:
|
||||
import live2d.tha3.app.app as live2d
|
||||
from live2d import *
|
||||
def launch_live2d_gui():
|
||||
live2d.launch_gui(mode, "separable_float")
|
||||
import talkinghead.tha3.app.app as talkinghead
|
||||
from talkinghead import *
|
||||
def launch_talkinghead_gui():
|
||||
talkinghead.launch_gui(mode, "separable_float")
|
||||
#choices=['standard_float', 'separable_float', 'standard_half', 'separable_half'],
|
||||
#choices='The device to use for PyTorch ("cuda" for GPU, "cpu" for CPU).'
|
||||
live2d_thread = threading.Thread(target=launch_live2d_gui)
|
||||
live2d_thread.daemon = True # Set the thread as a daemon thread
|
||||
live2d_thread.start()
|
||||
talkinghead_thread = threading.Thread(target=launch_talkinghead_gui)
|
||||
talkinghead_thread.daemon = True # Set the thread as a daemon thread
|
||||
talkinghead_thread.start()
|
||||
|
||||
except ModuleNotFoundError:
|
||||
print("Error: Could not import the 'live2d' module.")
|
||||
print("Error: Could not import the 'talkinghead' module.")
|
||||
|
||||
if "caption" in modules:
|
||||
print("Initializing an image captioning model...")
|
||||
@@ -625,8 +625,8 @@ def api_classify():
|
||||
classification = classify_text(data["text"])
|
||||
print("Classification output:", classification, sep="\n")
|
||||
gc.collect()
|
||||
if "live2d" in modules: #send emotion to live2d
|
||||
live2d.setEmotion(classification)
|
||||
if "talkinghead" in modules: #send emotion to talkinghead
|
||||
talkinghead.setEmotion(classification)
|
||||
return jsonify({"classification": classification})
|
||||
|
||||
|
||||
@@ -635,31 +635,31 @@ def api_classify():
|
||||
def api_classify_labels():
|
||||
classification = classify_text("")
|
||||
labels = [x["label"] for x in classification]
|
||||
if "live2d" in modules:
|
||||
labels.append('live2d') # Add 'live2d' to the labels list
|
||||
if "talkinghead" in modules:
|
||||
labels.append('talkinghead') # Add 'talkinghead' to the labels list
|
||||
return jsonify({"labels": labels})
|
||||
|
||||
@app.route("/api/live2d/load", methods=["POST"])
|
||||
@app.route("/api/talkinghead/load", methods=["POST"])
|
||||
def live_load():
|
||||
file = request.files['file']
|
||||
# convert stream to bytes and pass to live2d_load
|
||||
return live2d.live2d_load_file(file.stream)
|
||||
# convert stream to bytes and pass to talkinghead_load
|
||||
return talkinghead.talkinghead_load_file(file.stream)
|
||||
|
||||
@app.route('/api/live2d/unload')
|
||||
@app.route('/api/talkinghead/unload')
|
||||
def live_unload():
|
||||
return live2d.unload()
|
||||
return talkinghead.unload()
|
||||
|
||||
@app.route('/api/live2d/start_talking')
|
||||
@app.route('/api/talkinghead/start_talking')
|
||||
def start_talking():
|
||||
return live2d.start_talking()
|
||||
return talkinghead.start_talking()
|
||||
|
||||
@app.route('/api/live2d/stop_talking')
|
||||
@app.route('/api/talkinghead/stop_talking')
|
||||
def stop_talking():
|
||||
return live2d.stop_talking()
|
||||
return talkinghead.stop_talking()
|
||||
|
||||
@app.route('/api/live2d/result_feed')
|
||||
@app.route('/api/talkinghead/result_feed')
|
||||
def result_feed():
|
||||
return live2d.result_feed()
|
||||
return talkinghead.result_feed()
|
||||
|
||||
@app.route("/api/coqui-tts/load", methods=["GET"])
|
||||
@require_module("coqui-tts")
|
||||
|
||||
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
@@ -43,7 +43,7 @@ lasttranisitiondPose = "NotInit"
|
||||
inMotion = False
|
||||
fps = 0
|
||||
current_pose = None
|
||||
storepath = os.path.join(os.getcwd(), "live2d", "emotions")
|
||||
storepath = os.path.join(os.getcwd(), "talkinghead", "emotions")
|
||||
|
||||
# Flask setup
|
||||
app = Flask(__name__)
|
||||
@@ -99,7 +99,7 @@ def result_feed():
|
||||
time.sleep(0.1)
|
||||
return Response(generate(), mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||
|
||||
def live2d_load_file(stream):
|
||||
def talkinghead_load_file(stream):
|
||||
global global_source_image
|
||||
global global_reload
|
||||
global global_timer_paused
|
||||
@@ -112,7 +112,7 @@ def live2d_load_file(stream):
|
||||
global_reload = Image.open(BytesIO(img_data.getvalue())) # Set the global_reload to the copy of the image data
|
||||
except Image.UnidentifiedImageError:
|
||||
print(f"Could not load image from file, loading blank")
|
||||
full_path = os.path.join(os.getcwd(), "live2d\\tha3\\images\\inital.png")
|
||||
full_path = os.path.join(os.getcwd(), "talkinghead\\tha3\\images\\inital.png")
|
||||
MainFrame.load_image(None, full_path)
|
||||
global_timer_paused = True
|
||||
return 'OK'
|
||||
@@ -140,7 +140,7 @@ def launch_gui(device, model):
|
||||
main_frame.SetSize((750, 600))
|
||||
|
||||
#Lload default image (you can pass args.char if required)
|
||||
full_path = os.path.join(os.getcwd(), "live2d\\tha3\\images\\inital.png")
|
||||
full_path = os.path.join(os.getcwd(), "talkinghead\\tha3\\images\\inital.png")
|
||||
main_frame.load_image(None, full_path)
|
||||
|
||||
#main_frame.Show(True)
|
||||
@@ -969,7 +969,7 @@ class MainFrame(wx.Frame):
|
||||
|
||||
if random.random() <= 0.01:
|
||||
trimmed_fps = round(fps, 1)
|
||||
#print("Live2d FPS: {:.1f}".format(trimmed_fps))
|
||||
#print("talkinghead FPS: {:.1f}".format(trimmed_fps))
|
||||
|
||||
|
||||
#Store current pose to use as last pose on next loop
|
||||
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |