mirror of
https://github.com/believethehype/nostrdvm.git
synced 2025-06-14 22:30:51 +02:00
adding nip98, nostr.build account, convert tts to mp3 before upload
This commit is contained in:
parent
62cb455528
commit
b8ebdddcb3
@ -18,6 +18,7 @@ REPLICATE_API_TOKEN = "" #API Key to run models on replicate.com
|
|||||||
HUGGINGFACE_EMAIL = ""
|
HUGGINGFACE_EMAIL = ""
|
||||||
HUGGINGFACE_PASSWORD = ""
|
HUGGINGFACE_PASSWORD = ""
|
||||||
COINSTATSOPENAPI_KEY = ""
|
COINSTATSOPENAPI_KEY = ""
|
||||||
|
NOSTR_BUILD_ACCOUNT_PK = "" # Enter the private key of an account you use with nostr.build
|
||||||
|
|
||||||
# We will automatically create dtags and private keys based on the identifier variable in main.
|
# We will automatically create dtags and private keys based on the identifier variable in main.
|
||||||
# If your DVM already has a dtag and private key you can replace it here before publishing the DTAG to not create a new one.
|
# If your DVM already has a dtag and private key you can replace it here before publishing the DTAG to not create a new one.
|
||||||
|
@ -88,7 +88,7 @@ def check_server_status(jobID, address) -> str | pd.DataFrame:
|
|||||||
if content_type == "image/jpeg":
|
if content_type == "image/jpeg":
|
||||||
image = Image.open(io.BytesIO(response.content))
|
image = Image.open(io.BytesIO(response.content))
|
||||||
image.save("./outputs/image.jpg")
|
image.save("./outputs/image.jpg")
|
||||||
result = upload_media_to_hoster("./outputs/image.jpg")
|
result = asyncio.run(upload_media_to_hoster("./outputs/image.jpg"))
|
||||||
os.remove("./outputs/image.jpg")
|
os.remove("./outputs/image.jpg")
|
||||||
return result
|
return result
|
||||||
elif content_type == 'video/mp4':
|
elif content_type == 'video/mp4':
|
||||||
@ -97,7 +97,7 @@ def check_server_status(jobID, address) -> str | pd.DataFrame:
|
|||||||
f.close()
|
f.close()
|
||||||
clip = VideoFileClip("./outputs/video.mp4")
|
clip = VideoFileClip("./outputs/video.mp4")
|
||||||
clip.write_videofile("./outputs/video2.mp4")
|
clip.write_videofile("./outputs/video2.mp4")
|
||||||
result = upload_media_to_hoster("./outputs/video2.mp4")
|
result = asyncio.run(upload_media_to_hoster("./outputs/video2.mp4"))
|
||||||
clip.close()
|
clip.close()
|
||||||
os.remove("./outputs/video.mp4")
|
os.remove("./outputs/video.mp4")
|
||||||
os.remove("./outputs/video2.mp4")
|
os.remove("./outputs/video2.mp4")
|
||||||
|
@ -72,7 +72,7 @@ class MediaConverter(DVMTaskInterface):
|
|||||||
|
|
||||||
async def process(self, request_form):
|
async def process(self, request_form):
|
||||||
options = self.set_options(request_form)
|
options = self.set_options(request_form)
|
||||||
url = upload_media_to_hoster(options["filepath"])
|
url = await upload_media_to_hoster(options["filepath"])
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ class ImageGenerationDALLE(DVMTaskInterface):
|
|||||||
response = requests.get(image_url)
|
response = requests.get(image_url)
|
||||||
image = Image.open(BytesIO(response.content)).convert("RGB")
|
image = Image.open(BytesIO(response.content)).convert("RGB")
|
||||||
image.save("./outputs/image.jpg")
|
image.save("./outputs/image.jpg")
|
||||||
result = upload_media_to_hoster("./outputs/image.jpg")
|
result = await upload_media_to_hoster("./outputs/image.jpg")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -107,7 +107,7 @@ class ImageGenerationReplicateSDXL(DVMTaskInterface):
|
|||||||
response = requests.get(output[0])
|
response = requests.get(output[0])
|
||||||
image = Image.open(BytesIO(response.content)).convert("RGB")
|
image = Image.open(BytesIO(response.content)).convert("RGB")
|
||||||
image.save("./outputs/image.jpg")
|
image.save("./outputs/image.jpg")
|
||||||
result = upload_media_to_hoster("./outputs/image.jpg")
|
result = await upload_media_to_hoster("./outputs/image.jpg")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -136,7 +136,7 @@ class ImageGenerationMLX(DVMTaskInterface):
|
|||||||
# Save them to disc
|
# Save them to disc
|
||||||
image = Image.fromarray(x.__array__())
|
image = Image.fromarray(x.__array__())
|
||||||
image.save("./outputs/image.jpg")
|
image.save("./outputs/image.jpg")
|
||||||
result = upload_media_to_hoster("./outputs/image.jpg")
|
result = await upload_media_to_hoster("./outputs/image.jpg")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
import ffmpegio
|
||||||
from nostr_sdk import Kind
|
from nostr_sdk import Kind
|
||||||
|
|
||||||
|
from nostr_dvm.utils.mediasource_utils import organize_input_media_data
|
||||||
from nostr_dvm.utils.nip88_utils import NIP88Config
|
from nostr_dvm.utils.nip88_utils import NIP88Config
|
||||||
|
|
||||||
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
|
||||||
@ -37,6 +39,7 @@ class TextToSpeech(DVMTaskInterface):
|
|||||||
async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None,
|
async def init_dvm(self, name, dvm_config: DVMConfig, nip89config: NIP89Config, nip88config: NIP88Config = None,
|
||||||
admin_config: AdminConfig = None, options=None):
|
admin_config: AdminConfig = None, options=None):
|
||||||
dvm_config.SCRIPT = os.path.abspath(__file__)
|
dvm_config.SCRIPT = os.path.abspath(__file__)
|
||||||
|
self.dvm_config = dvm_config
|
||||||
|
|
||||||
async def is_input_supported(self, tags, client=None, dvm_config=None):
|
async def is_input_supported(self, tags, client=None, dvm_config=None):
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
@ -132,8 +135,14 @@ class TextToSpeech(DVMTaskInterface):
|
|||||||
|
|
||||||
tts.tts_to_file(
|
tts.tts_to_file(
|
||||||
text=text_clean,
|
text=text_clean,
|
||||||
speaker_wav=options["input_wav"], language=options["language"], file_path="outputs/output.mp3")
|
speaker_wav=options["input_wav"], language=options["language"], file_path="outputs/output.wav")
|
||||||
result = upload_media_to_hoster("outputs/output.mp3")
|
|
||||||
|
print("Converting Audio")
|
||||||
|
final_filename = "outputs/output.mp3"
|
||||||
|
fs, x = ffmpegio.audio.read("outputs/output.wav", sample_fmt='dbl', ac=1)
|
||||||
|
ffmpegio.audio.write(final_filename, fs, x, overwrite=True)
|
||||||
|
|
||||||
|
result = await upload_media_to_hoster(final_filename, dvm_config=self.dvm_config)
|
||||||
print(result)
|
print(result)
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -99,7 +99,7 @@ class VideoGenerationReplicateSVD(DVMTaskInterface):
|
|||||||
print(output)
|
print(output)
|
||||||
|
|
||||||
urllib.request.urlretrieve(output, "./outputs/svd.mp4")
|
urllib.request.urlretrieve(output, "./outputs/svd.mp4")
|
||||||
result = upload_media_to_hoster("./outputs/svd.mp4")
|
result = await upload_media_to_hoster("./outputs/svd.mp4")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -6,7 +6,6 @@ from nostr_dvm.utils.nip88_utils import NIP88Config
|
|||||||
from nostr_dvm.utils.nip89_utils import NIP89Config
|
from nostr_dvm.utils.nip89_utils import NIP89Config
|
||||||
from nostr_dvm.utils.nostr_utils import check_and_set_private_key
|
from nostr_dvm.utils.nostr_utils import check_and_set_private_key
|
||||||
from nostr_dvm.utils.outbox_utils import AVOID_OUTBOX_RELAY_LIST
|
from nostr_dvm.utils.outbox_utils import AVOID_OUTBOX_RELAY_LIST
|
||||||
from nostr_dvm.utils.output_utils import PostProcessFunctionType
|
|
||||||
from nostr_dvm.utils.zap_utils import check_and_set_ln_bits_keys
|
from nostr_dvm.utils.zap_utils import check_and_set_ln_bits_keys
|
||||||
|
|
||||||
class DVMConfig:
|
class DVMConfig:
|
||||||
@ -31,7 +30,7 @@ class DVMConfig:
|
|||||||
|
|
||||||
RELAY_TIMEOUT = 5
|
RELAY_TIMEOUT = 5
|
||||||
RELAY_LONG_TIMEOUT = 30
|
RELAY_LONG_TIMEOUT = 30
|
||||||
EXTERNAL_POST_PROCESS_TYPE = PostProcessFunctionType.NONE # Leave this on None, except the DVM is external
|
EXTERNAL_POST_PROCESS_TYPE = 0 # Leave this on None, except the DVM is external
|
||||||
LNBITS_INVOICE_KEY = '' # Will all automatically generated by default, or read from .env
|
LNBITS_INVOICE_KEY = '' # Will all automatically generated by default, or read from .env
|
||||||
LNBITS_ADMIN_KEY = '' # In order to pay invoices, e.g. from the bot to DVMs, or reimburse users.
|
LNBITS_ADMIN_KEY = '' # In order to pay invoices, e.g. from the bot to DVMs, or reimburse users.
|
||||||
LNBITS_URL = 'https://lnbits.com'
|
LNBITS_URL = 'https://lnbits.com'
|
||||||
@ -42,8 +41,8 @@ class DVMConfig:
|
|||||||
DB: str
|
DB: str
|
||||||
NEW_USER_BALANCE: int = 0 # Free credits for new users
|
NEW_USER_BALANCE: int = 0 # Free credits for new users
|
||||||
SUBSCRIPTION_MANAGEMENT = 'https://noogle.lol/discovery'
|
SUBSCRIPTION_MANAGEMENT = 'https://noogle.lol/discovery'
|
||||||
NIP88: NIP88Config
|
NIP88: NIP88Config = NIP88Config()
|
||||||
NIP89: NIP89Config
|
NIP89: NIP89Config = NIP89Config()
|
||||||
SEND_FEEDBACK_EVENTS = True
|
SEND_FEEDBACK_EVENTS = True
|
||||||
SHOW_RESULT_BEFORE_PAYMENT: bool = False # if this is true show results even when not paid right after autoprocess
|
SHOW_RESULT_BEFORE_PAYMENT: bool = False # if this is true show results even when not paid right after autoprocess
|
||||||
SCHEDULE_UPDATES_SECONDS = 0
|
SCHEDULE_UPDATES_SECONDS = 0
|
||||||
|
@ -31,9 +31,9 @@ async def nip89_announce_tasks(dvm_config, client):
|
|||||||
keys = Keys.parse(dvm_config.NIP89.PK)
|
keys = Keys.parse(dvm_config.NIP89.PK)
|
||||||
content = dvm_config.NIP89.CONTENT
|
content = dvm_config.NIP89.CONTENT
|
||||||
event = EventBuilder(EventDefinitions.KIND_ANNOUNCEMENT, content, [k_tag, d_tag]).to_event(keys)
|
event = EventBuilder(EventDefinitions.KIND_ANNOUNCEMENT, content, [k_tag, d_tag]).to_event(keys)
|
||||||
evenid = await send_event(event, client=client, dvm_config=dvm_config)
|
eventid = await send_event(event, client=client, dvm_config=dvm_config)
|
||||||
|
|
||||||
print(bcolors.BLUE + "[" + dvm_config.NIP89.NAME + "] Announced NIP 89 for " + dvm_config.NIP89.NAME +" (" + evenid.to_hex() +")" + bcolors.ENDC)
|
print(bcolors.BLUE + "[" + dvm_config.NIP89.NAME + "] Announced NIP 89 for " + dvm_config.NIP89.NAME +" (" + eventid.to_hex() +")" + bcolors.ENDC)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
20
nostr_dvm/utils/nip98_utils.py
Normal file
20
nostr_dvm/utils/nip98_utils.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
from nostr_sdk import EventBuilder, Tag, Kind, Keys
|
||||||
|
|
||||||
|
|
||||||
|
def sha256sum(filename):
|
||||||
|
with open(filename, 'rb', buffering=0) as f:
|
||||||
|
return hashlib.file_digest(f, 'sha256').hexdigest()
|
||||||
|
|
||||||
|
async def generate_nip98_header(filepath, dvm_config):
|
||||||
|
keys = Keys.parse(dvm_config.NIP89.PK)
|
||||||
|
utag = Tag.parse(["u", "https://nostr.build/api/v2/upload/files"])
|
||||||
|
methodtag = Tag.parse(["method", "POST"])
|
||||||
|
payloadtag = Tag.parse(["payload", sha256sum(filepath)])
|
||||||
|
event = EventBuilder(Kind(27235), "", [utag, methodtag, payloadtag]).to_event(keys)
|
||||||
|
|
||||||
|
encoded_nip98_event = base64.b64encode(event.as_json().encode('utf-8')).decode('utf-8')
|
||||||
|
|
||||||
|
return "Nostr " + encoded_nip98_event
|
||||||
|
|
@ -6,11 +6,14 @@ from types import NoneType
|
|||||||
|
|
||||||
import emoji
|
import emoji
|
||||||
import requests
|
import requests
|
||||||
from nostr_sdk import Tag, PublicKey, EventId
|
from nostr_sdk import Tag, PublicKey, EventId, Keys
|
||||||
from pyupload.uploader import CatboxUploader
|
from pyupload.uploader import CatboxUploader
|
||||||
|
|
||||||
import pandas
|
import pandas
|
||||||
|
|
||||||
|
from nostr_dvm.utils.dvmconfig import DVMConfig
|
||||||
|
from nostr_dvm.utils.nip98_utils import generate_nip98_header
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Post process results to either given output format or a Nostr readable plain text.
|
Post process results to either given output format or a Nostr readable plain text.
|
||||||
'''
|
'''
|
||||||
@ -146,26 +149,35 @@ Will probably need to switch to another system in the future.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def upload_media_to_hoster(filepath: str):
|
async def upload_media_to_hoster(filepath: str, dvm_config=None, usealternativeforlargefiles=True):
|
||||||
|
|
||||||
|
if dvm_config is None:
|
||||||
|
dvm_config = DVMConfig()
|
||||||
|
dvm_config.NIP89.PK = Keys.parse(os.getenv("NOSTR_BUILD_ACCOUNT_PK")).secret_key().to_hex()
|
||||||
|
|
||||||
print("Uploading image: " + filepath)
|
print("Uploading image: " + filepath)
|
||||||
try:
|
try:
|
||||||
files = {'file': open(filepath, 'rb')}
|
files = {'file': open(filepath, 'rb')}
|
||||||
file_stats = os.stat(filepath)
|
file_stats = os.stat(filepath)
|
||||||
sizeinmb = file_stats.st_size / (1024 * 1024)
|
sizeinmb = file_stats.st_size / (1024 * 1024)
|
||||||
print("Filesize of Uploaded media: " + str(sizeinmb) + " Mb.")
|
print("Filesize of Uploaded media: " + str(sizeinmb) + " Mb.")
|
||||||
if sizeinmb > 25:
|
if sizeinmb > 25 and usealternativeforlargefiles:
|
||||||
print("Filesize over Nostr.build limited, using catbox")
|
print("Filesize over Nostr.build limited, using catbox")
|
||||||
uploader = CatboxUploader(filepath)
|
uploader = CatboxUploader(filepath)
|
||||||
result = uploader.execute()
|
result = uploader.execute()
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
url = 'https://nostr.build/api/v2/upload/files'
|
url = 'https://nostr.build/api/v2/upload/files'
|
||||||
response = requests.post(url, files=files)
|
auth = await generate_nip98_header(filepath, dvm_config)
|
||||||
|
headers = {'authorization': auth}
|
||||||
|
|
||||||
|
response = requests.post(url, files=files, headers=headers)
|
||||||
print(response.text)
|
print(response.text)
|
||||||
json_object = json.loads(response.text)
|
json_object = json.loads(response.text)
|
||||||
result = json_object["data"][0]["url"]
|
result = json_object["data"][0]["url"]
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
try:
|
try:
|
||||||
uploader = CatboxUploader(filepath)
|
uploader = CatboxUploader(filepath)
|
||||||
result = uploader.execute()
|
result = uploader.execute()
|
||||||
|
2
setup.py
2
setup.py
@ -1,6 +1,6 @@
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
VERSION = '0.6.29'
|
VERSION = '0.6.30'
|
||||||
DESCRIPTION = 'A framework to build and run Nostr NIP90 Data Vending Machines'
|
DESCRIPTION = 'A framework to build and run Nostr NIP90 Data Vending Machines'
|
||||||
LONG_DESCRIPTION = ('A framework to build and run Nostr NIP90 Data Vending Machines. See the github repository for more information')
|
LONG_DESCRIPTION = ('A framework to build and run Nostr NIP90 Data Vending Machines. See the github repository for more information')
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ if __name__ == '__main__':
|
|||||||
dvm_config = build_default_config(identifier)
|
dvm_config = build_default_config(identifier)
|
||||||
dvm_config.USE_OWN_VENV = True
|
dvm_config.USE_OWN_VENV = True
|
||||||
dvm_config.FIX_COST = 0
|
dvm_config.FIX_COST = 0
|
||||||
dvm_config.PER_UNIT_COST = 0.2
|
dvm_config.PER_UNIT_COST = 0.1
|
||||||
admin_config_tts.LUD16 = dvm_config.LN_ADDRESS
|
admin_config_tts.LUD16 = dvm_config.LN_ADDRESS
|
||||||
# use an alternative local wav file you want to use for cloning
|
# use an alternative local wav file you want to use for cloning
|
||||||
options = {'input_file': ""}
|
options = {'input_file': ""}
|
||||||
|
@ -1,3 +1,21 @@
|
|||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import dotenv
|
||||||
|
from nostr_sdk import Keys
|
||||||
|
|
||||||
|
|
||||||
from nostr_dvm.utils.output_utils import upload_media_to_hoster
|
from nostr_dvm.utils.output_utils import upload_media_to_hoster
|
||||||
|
|
||||||
upload_media_to_hoster("tests/output.wav")
|
if __name__ == '__main__':
|
||||||
|
env_path = Path('.env')
|
||||||
|
if env_path.is_file():
|
||||||
|
print(f'loading environment from {env_path.resolve()}')
|
||||||
|
dotenv.load_dotenv(env_path, verbose=True, override=True)
|
||||||
|
else:
|
||||||
|
raise FileNotFoundError(f'.env file not found at {env_path} ')
|
||||||
|
|
||||||
|
|
||||||
|
asyncio.run(upload_media_to_hoster("tests/output.wav"))
|
||||||
|
# asyncio.run(upload_media_to_hoster("tests/test.jpeg", dvm_config))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user