commit
b0bfb860ef
|
@ -21,8 +21,10 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import smartcrop
|
||||
from datetime import datetime
|
||||
import json
|
||||
from PIL import Image
|
||||
from shutil import copyfile
|
||||
from uuid import uuid4
|
||||
from markupsafe import escape # dependency of flask
|
||||
|
@ -752,9 +754,19 @@ def move_coverfile(meta, db_book):
|
|||
else:
|
||||
cover_file = os.path.join(constants.STATIC_DIR, 'generic_cover.jpg')
|
||||
new_cover_path = os.path.join(config.config_calibre_dir, db_book.path)
|
||||
|
||||
try:
|
||||
os.makedirs(new_cover_path, exist_ok=True)
|
||||
copyfile(cover_file, os.path.join(new_cover_path, "cover.jpg"))
|
||||
image = Image.open(cover_file)
|
||||
|
||||
# crop image to square 150x150 using smartcrop
|
||||
cropper = smartcrop.SmartCrop()
|
||||
result = cropper.crop(image, 150, 150)
|
||||
x, y, width, height = result['top_crop']['x'], result['top_crop']['y'], \
|
||||
result['top_crop']['width'], result['top_crop']['height']
|
||||
cropped_image = image.crop((x, y, x + width, y + height))
|
||||
cropped_image.save(os.path.join(new_cover_path, "cover.jpg"))
|
||||
|
||||
if meta.cover:
|
||||
os.unlink(meta.cover)
|
||||
except OSError as e:
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
.tooltip.bottom .tooltip-inner {
|
||||
font-size: 13px;
|
||||
font-family: Open Sans Semibold, Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||
|
@ -139,9 +138,9 @@ table .bg-dark-danger a { color: #fff; }
|
|||
.container-fluid .new-books h2 { margin: 50px 0 0 0; }
|
||||
|
||||
.container-fluid .book {
|
||||
margin-top: 20px;
|
||||
margin-right: 10px;
|
||||
max-width: 150px;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
max-width: 120px; /* Adjust this value as needed */
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
|
@ -457,5 +456,17 @@ div.log {
|
|||
#detailcover:fullscreen { cursor:zoom-out; border: 0; }
|
||||
|
||||
.error-list {
|
||||
margin-top: 5px;
|
||||
}
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.container-fluid .book {
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
max-width: 120px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import os
|
||||
import hashlib
|
||||
import shutil
|
||||
import subprocess
|
||||
from subprocess import run
|
||||
from tempfile import gettempdir
|
||||
from flask_babel import gettext as _
|
||||
|
||||
|
@ -262,15 +262,25 @@ def video_metadata(tmp_file_path, original_file_name, original_file_extension):
|
|||
pubdate="",
|
||||
identifiers=[])
|
||||
return meta
|
||||
|
||||
|
||||
|
||||
def video_cover(tmp_file_path):
|
||||
""" generate cover image from video using ffmpeg """
|
||||
"""generate cover image from video using ffmpeg"""
|
||||
ffmpeg_executable = os.getenv('FFMPEG_PATH', 'ffmpeg')
|
||||
ffmpeg_output_file = os.path.splitext(tmp_file_path)[0] + '.cover.jpg'
|
||||
ffmpeg_args = [
|
||||
ffmpeg_executable,
|
||||
'-i', tmp_file_path,
|
||||
'-vframes', '1',
|
||||
'-y', ffmpeg_output_file
|
||||
]
|
||||
|
||||
try:
|
||||
subprocess.call([ffmpeg_executable, '-i', tmp_file_path, '-vframes', '1', '-y', os.path.splitext(tmp_file_path)[0] + '.cover.jpg'])
|
||||
return None
|
||||
except Exception as ex:
|
||||
log.warning('Cannot extract cover image, using default: %s', ex)
|
||||
ffmpeg_result = run(ffmpeg_args, capture_output=True, check=True)
|
||||
log.debug(f"ffmpeg output: {ffmpeg_result.stdout}")
|
||||
|
||||
except Exception as e:
|
||||
log.warning(f"ffmpeg failed: {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue