Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

环境升级以及小优化 #33

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ cache/*
.vscode
test.json
*.pyc
/list.txt
/venv/
/.idea
10 changes: 4 additions & 6 deletions crawler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

if __name__ == "__main__":
parsed_json = object
if (len(sys.argv) == 1 or sys.argv[1]=='-t'):
if len(sys.argv) == 1 or sys.argv[1] == '-t':
print("----------")
print("Start to create the latest gadio video...")
id = Crawler.get_latest()
Expand All @@ -17,8 +17,6 @@
parsed_json = Crawler.crawl(radio_id)
radio = Radio.load_from_json(parsed_json)
Crawler.get_headers(radio)
if (len(sys.argv) >= 2):
if ('-t' in sys.argv):
{}
else:
Crawler.download_assets(radio, os.curdir+os.sep+'cache')
if len(sys.argv) >= 2:
if '-t' not in sys.argv:
Crawler.download_assets(radio, os.curdir + os.sep + 'cache')
2 changes: 1 addition & 1 deletion gadio/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from gadio.crawlers import *
from gadio.configs import *
from gadio.media import *
from gadio.models import *
from gadio.models import *
18 changes: 9 additions & 9 deletions gadio/configs/config.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import os

config = {
'fps':2,
'width':1920,
'height':1080,
'fps': 2,
'width': 1920,
'height': 1080,
'title_font_size': 53,
'content_font_size': 36,
'gcores_title_color': (255,255,255,246),
'gcores_content_color': (255,255,255,205),
'background_color':"#FFFFFF",
'gcores_title_color': (255, 255, 255, 246),
'gcores_content_color': (255, 255, 255, 205),
'background_color': "#FFFFFF",
'title_font': os.sep.join([os.curdir, 'gadio', 'utils', 'PingFang-Heavy.ttf']),
'content_font': os.sep.join([os.curdir, 'gadio', 'utils', 'PingFang-Medium.ttf']),
'gcores_logo_name': os.sep.join([os.curdir, 'gadio', 'utils', 'gcores.png']),
'gcores_qr_name': os.sep.join([os.curdir, 'gadio', 'utils', 'qr.png']),
'test':False,
'start_offset':5
}
'test': False,
'start_offset': 5
}
47 changes: 20 additions & 27 deletions gadio/crawlers/crawler.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import json
import os
import re
import sys
import urllib.request

import requests
from MyQR import myqr
from PIL import Image

from gadio.configs.config import config
from gadio.models.asset import Image, Audio
from gadio.models.radio import Radio
from gadio.models.user import User
from gadio.models.page import Page
from gadio.configs.api import api
from gadio.models.asset import Audio
from gadio.models.radio import Radio
from gadio.text.text import *

#api = "https://www.gcores.com/gapi/v1/radios/112068?include=category,media,djs,media.timelines"

class Crawler():
# api = "https://www.gcores.com/gapi/v1/radios/112068?include=category,media,djs,media.timelines"

class Crawler:

@staticmethod
def crawl(gadio_id: int):
Expand All @@ -30,10 +25,10 @@ def crawl(gadio_id: int):
print("Extracting information from ", gadio_id)
content = requests.get(url).content
parsed = json.loads(content)
#print(parsed)
# print(parsed)
dictionary = dict()
for i in parsed['included']:
if (i['type'] in dictionary.keys()):
if i['type'] in dictionary.keys():
dictionary[i['type']] += 1
else:
dictionary[i['type']] = 1
Expand All @@ -42,8 +37,8 @@ def crawl(gadio_id: int):
if not os.path.exists(cache_dir):
print("Folder", cache_dir, 'does not exist. Creating...')
os.makedirs(cache_dir)
with open(cache_dir+os.sep+'data.json', 'w', encoding='utf-8') as outfile:
#print(cache_dir)
with open(cache_dir + os.sep + 'data.json', 'w', encoding='utf-8') as outfile:
# print(cache_dir)
json.dump(parsed, outfile, ensure_ascii=False, indent=4)
return parsed

Expand All @@ -54,7 +49,7 @@ def download_image(image: Image, file_dir: str):
print("Folder", file_dir, 'does not exist. Creating...')
os.makedirs(file_dir)
print("Saving image to", image.local_name)
r = urllib.request.urlretrieve(image.image_url, file_dir + os.sep + image.local_name)
urllib.request.urlretrieve(image.image_url, file_dir + os.sep + image.local_name)
return 1
except Exception as e:
print("Error", e)
Expand All @@ -67,15 +62,14 @@ def download_audio(audio: Audio, file_dir: str):
print("Folder", file_dir, 'does not exist. Creating...')
os.makedirs(file_dir)
print("Saving audio to", audio.local_name)
r = urllib.request.urlretrieve(audio.audio_url, file_dir + os.sep + audio.local_name)
urllib.request.urlretrieve(audio.audio_url, file_dir + os.sep + audio.local_name)
return 1
except Exception as e:
print("Error", e)
return 0
return

@staticmethod
def download_assets(radio: Radio, file_dir: str, with_quote: bool):
def download_assets(radio: Radio, file_dir: str, with_quote: bool = False):
id = str(radio.radio_id)
file_dir = file_dir + os.sep + id
Crawler.download_image(radio.cover, file_dir)
Expand Down Expand Up @@ -103,21 +97,20 @@ def get_headers(radio: Radio):
offset = config['start_offset']
headers = []
for i in radio.timestamps:
if (i not in radio.timeline.keys()):
if i not in radio.timeline.keys():
continue
else:
seconds = i + 1 if i == 0 else i
time = seconds_to_time(str(seconds + offset))
time = seconds_to_time(seconds + offset)
headers.append(time + " " + radio.timeline[i].title)
with open(os.sep.join(['.', "output", radio.radio_id + "_headers.txt"]), 'w+', encoding='utf-8') as links:
length = 0
last = ""
for header in headers:
line= header+"⭐"
length+=len(line)
if(length>990): # Bilibili comment length 1000
line = header + "⭐"
length += len(line)
if length > 990: # Bilibili comment length 1000
links.write("\n\n")
length=len(line)
length = len(line)
links.writelines(line)
links.close()

Expand All @@ -141,4 +134,4 @@ def make_quote_qr_image(text, name, file_dir):
save_dir=file_dir,
)
except:
print("wrong qr code")
print("wrong qr code")
65 changes: 40 additions & 25 deletions gadio/media/frame.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

import os

import cv2
import numpy as np
from cv2 import VideoWriter_fourcc
import pillow_avif
from PIL import Image, ImageDraw, ImageFont

from gadio.configs.config import config
Expand All @@ -12,7 +11,7 @@
from gadio.models.page import Page


class Frame():
class Frame:
width = config['width']
height = config['height']
title_font = ImageFont.truetype(
Expand All @@ -23,7 +22,7 @@ class Frame():
content_wrapper = Wrapper(content_font)

def __init__(self, *args, **kwargs):
return super().__init__(*args, **kwargs)
super().__init__(*args, **kwargs)

@staticmethod
def create_cover(radio: Radio):
Expand Down Expand Up @@ -62,14 +61,23 @@ def create_page(page: Page, radio: Radio):
np.array -- An numpy array representing cv2 image.
"""
image_suffix = page.image.suffix
if (image_suffix == "" or image_suffix.lower() == '.gif'):
if image_suffix == "" or image_suffix.lower() == '.gif':
# If image is not found or image is gif, load cover as background
image_dir = os.sep.join(['cache', str(radio.radio_id), radio.cover.local_name])
else:
image_dir = os.sep.join(['cache', str(radio.radio_id), page.image.local_name])
qr_dir = os.sep.join(['cache', str(radio.radio_id), 'qr_quotes', page.image.local_name.split('.')[0] + ".png"])

image = cv2.imread(image_dir)
if image is None:
match image_suffix:
case '.avif':
pil_image = Image.open(image_dir)
image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
case _:
# If image can't load, then load cover as background
image = cv2.imread(os.sep.join(['cache', str(radio.radio_id), radio.cover.local_name]))
print(image_dir)
image_suffix = page.image.suffix
background_image = Frame.expand_frame(image, Frame.width, Frame.height)
background_image = cv2.GaussianBlur(background_image, (255, 255), 255)
Expand All @@ -85,29 +93,29 @@ def create_page(page: Page, radio: Radio):
mask = Image.new('RGBA', (Frame.width, Frame.height), color=(0, 0, 0, 128))
frame.paste(mask, (0, 0), mask=mask)

left_offset = int(round(245/1920 * Frame.width)) + int(round((550 - content_image.shape[1])/2))
top_offset = int(round(210/1080 * Frame.height)) + int(round((550 - content_image.shape[0])/2))
left_offset = int(round(245 / 1920 * Frame.width)) + int(round((550 - content_image.shape[1]) / 2))
top_offset = int(round(210 / 1080 * Frame.height)) + int(round((550 - content_image.shape[0]) / 2))

content_frame = Image.fromarray(content_rgb)
content_image_mask = Image.new('RGBA', (content_image.shape[1], content_image.shape[0]), color=(0, 0, 0, 26))
if (image_suffix == "" or image_suffix.lower() == '.gif'):
if image_suffix == "" or image_suffix.lower() == '.gif':
# if image is not properly downloaded or is gif, no content image should be added.
print("GIF will not be rendered in this page...")
else:
frame.paste(content_frame, (left_offset, top_offset))
frame.paste(content_image_mask, (left_offset, top_offset), mask = content_image_mask)
frame.paste(content_image_mask, (left_offset, top_offset), mask=content_image_mask)

try:
logo_image = Image.open(config['gcores_logo_name']).convert('RGBA')
qr_image = Image.open(config['gcores_qr_name']).convert('RGBA')
logo_left_offset = int(round(120/1920 * Frame.width))
logo_top_offset = int(round(52/1080 * Frame.height))
logo_left_offset = int(round(120 / 1920 * Frame.width))
logo_top_offset = int(round(52 / 1080 * Frame.height))
qr_left_offset = logo_left_offset
qr_top_offset = int(round(917/1080 * Frame.height))
qr_top_offset = int(round(917 / 1080 * Frame.height))
frame.paste(logo_image, (logo_left_offset, logo_top_offset), mask=logo_image)
frame.paste(qr_image, (qr_left_offset, qr_top_offset), mask=qr_image)
if os.path.exists(qr_dir):
qr_right_offset = int(round(1700/1920 * Frame.width))
qr_right_offset = int(round(1700 / 1920 * Frame.width))
page_qr_image = Image.open(qr_dir).convert('RGBA')
page_qr_image = page_qr_image.resize((86, 86))
frame.paste(page_qr_image, (qr_right_offset, qr_top_offset), mask=page_qr_image)
Expand All @@ -122,37 +130,44 @@ def create_page(page: Page, radio: Radio):
print('Title:', title_string)
raw_content = page.content
content_string = Frame.content_wrapper.wrap_string(raw_content, text_width_limit)
#print(content_string)
# print(content_string)

# Dimensions for text layout
text_top_offset = int(round(260 / 1080 * Frame.height))
text_left_offset = int(round(920 / 1920 * Frame.width))
title_height = Frame.title_font.getsize_multiline(title_string)[1]
title_left, title_top, title_right, title_bottom = Frame.title_font.getbbox(title_string)
title_height = title_bottom - title_top
# title_height = Frame.title_font.getsize_multiline(title_string)[1]
title_space_bottom = int(round(Frame.title_font.size * 0.9))
content_height_limit = int(round(574 / 1080 * Frame.height)) - title_height - title_space_bottom

content_space = int(round(Frame.content_font.size * 0.8))
actual_content_height = Frame.content_font.getsize_multiline(content_string, spacing=content_space)[1]
while (actual_content_height > content_height_limit):
content_left, content_top, content_right, content_bottom = Frame.title_font.getbbox(content_string)
actual_content_height = content_bottom - content_top
# actual_content_height = Frame.content_font.getsize_multiline(content_string, spacing=content_space)[1]
while actual_content_height > content_height_limit:
Frame.content_font = Frame.shrink_font(Frame.content_font, config['content_font'])
content_space = int(round(Frame.content_font.size * 0.8))
content_wrapper = Wrapper(Frame.content_font)
content_string = content_wrapper.wrap_string(raw_content, text_width_limit)
actual_content_height = Frame.content_font.getsize_multiline(content_string, spacing=content_space)[1]
content_left, content_top, content_right, content_bottom = Frame.title_font.getbbox(content_string)
actual_content_height = content_bottom - content_top
# actual_content_height = Frame.content_font.getsize_multiline(content_string, spacing=content_space)[1]
# print(actual_content_height)

print(content_string)
draw.text((text_left_offset, text_top_offset), title_string, config['gcores_title_color'], font=Frame.title_font)
draw.text((text_left_offset, text_top_offset + title_height + title_space_bottom), content_string, config['gcores_content_color'], font=Frame.content_font, spacing=content_space)
draw.text((text_left_offset, text_top_offset), title_string, config['gcores_title_color'],
font=Frame.title_font)
draw.text((text_left_offset, text_top_offset + title_height + title_space_bottom), content_string,
config['gcores_content_color'], font=Frame.content_font, spacing=content_space)

# Reset content_wrapper and content_font
Frame.content_font = ImageFont.truetype(config['content_font'], config['content_font_size'], encoding="utf-8")
Frame.content_wrapper = Wrapper(Frame.content_font)

cv2charimg = np.array(frame)
result = cv2.cvtColor(cv2charimg, cv2.COLOR_RGB2BGR)
# cv2.imwrite('test.jpg',result)
# cv2.waitKey()

return result

@staticmethod
Expand All @@ -176,8 +191,8 @@ def expand_frame(image, target_width, target_height):
ratio = min(width_ratio, height_ratio)
# in case width or height smaller than target after rounding.
actual_width = max(int(image.shape[1] / ratio), target_width)
actuai_height = max(int(image.shape[0] / ratio), target_height)
result = cv2.resize(image, (actual_width, actuai_height),
actual_height = max(int(image.shape[0] / ratio), target_height)
result = cv2.resize(image, (actual_width, actual_height),
interpolation=cv2.INTER_CUBIC)
left = int((result.shape[1] - target_width) / 2)
right = left + target_width
Expand Down Expand Up @@ -209,5 +224,5 @@ def shrink_frame(image, target_width, target_height):

@staticmethod
def shrink_font(font, font_family):
result_font = ImageFont.truetype(font_family, font.size-2, encoding="utf-8")
result_font = ImageFont.truetype(font_family, font.size - 2, encoding="utf-8")
return result_font
Loading
Loading