updated to 4k images from pptx

This commit is contained in:
2025-08-01 10:23:38 +03:00
parent c8bbbebb48
commit 1326543418
9 changed files with 82 additions and 30 deletions

19
app.py
View File

@@ -327,7 +327,8 @@ def edit_player(player_id):
hostname = request.form['hostname']
password = request.form['password'] if request.form['password'] else None
quickconnect_password = request.form['quickconnect_password'] if request.form['quickconnect_password'] else None
edit_player_util(player_id, username, hostname, password, quickconnect_password)
orientation = request.form.get('orientation', player.orientation) # <-- Get orientation
edit_player_util(player_id, username, hostname, password, quickconnect_password, orientation) # <-- Pass orientation
flash(f'Player "{username}" updated successfully.', 'success')
return redirect(url_for('player_page', player_id=player.id))
@@ -648,14 +649,14 @@ def create_admin(username, password):
from models.create_default_user import create_default_user
with app.app_context():
try:
db.session.execute(db.select(User).limit(1))
except Exception as e:
print("Database not initialized or missing tables. Re-initializing...")
db.create_all()
# Always ensure default user exists
create_default_user(db, User, bcrypt)
if not app.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
with app.app_context():
try:
db.session.execute(db.select(User).limit(1))
except Exception as e:
print("Database not initialized or missing tables. Re-initializing...")
db.create_all()
create_default_user(db, User, bcrypt)
# Add this at the end of app.py
if __name__ == '__main__':

Binary file not shown.

View File

@@ -49,11 +49,23 @@
</select>
</div>
</div>
<div class="col-md-6 col-12">
<div class="mb-3">
<label for="orientation" class="form-label">Group Orientation</label>
<select class="form-control {{ 'dark-mode' if theme == 'dark' else '' }}" id="orientation" name="orientation" required>
<option value="Landscape" selected>Landscape</option>
<option value="Portret">Portret</option>
</select>
</div>
</div>
</div>
<div class="alert alert-warning" role="alert">
<strong>Warning:</strong> Adding players to a group will delete their individual playlists.
All players in a group will share the same content.
</div>
<div id="orientation-warning" class="alert alert-danger d-none" role="alert">
No players with the selected orientation are available.
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Create Group</button>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
@@ -61,5 +73,38 @@
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Get all players and their orientations from the backend
const players = [
{% for player in players %}
{id: {{ player.id }}, username: "{{ player.username }}", orientation: "{{ player.orientation }}"},
{% endfor %}
];
const orientationSelect = document.getElementById('orientation');
const playersSelect = document.getElementById('players');
const orientationWarning = document.getElementById('orientation-warning');
function filterPlayers() {
const selectedOrientation = orientationSelect.value;
playersSelect.innerHTML = '';
let compatibleCount = 0;
players.forEach(player => {
if (player.orientation === selectedOrientation) {
const option = document.createElement('option');
option.value = player.id;
option.textContent = player.username;
playersSelect.appendChild(option);
compatibleCount++;
}
});
document.getElementById('orientation-warning').classList.toggle('d-none', compatibleCount > 0);
}
orientationSelect.addEventListener('change', filterPlayers);
// Initial filter on page load
filterPlayers();
</script>
</body>
</html>

View File

@@ -60,6 +60,13 @@
</div>
</div>
</div>
<div class="mb-3">
<label for="orientation" class="form-label">Orientation</label>
<select class="form-control {{ 'dark-mode' if theme == 'dark' else '' }}" id="orientation" name="orientation" required>
<option value="Landscape" {% if player.orientation == 'Landscape' %}selected{% endif %}>Landscape</option>
<option value="Portret" {% if player.orientation == 'Portret' %}selected{% endif %}>Portret</option>
</select>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Update Player</button>
<a href="{{ return_url }}" class="btn btn-secondary mt-3">Back to Player Page</a>

View File

@@ -106,8 +106,12 @@
&#9776;
</div>
<!-- Media Name -->
<div class="flex-grow-1 mb-2 mb-md-0">
<!-- Media Thumbnail and Name -->
<div class="flex-grow-1 mb-2 mb-md-0 d-flex align-items-center">
<img src="{{ url_for('static', filename='uploads/' ~ media.file_name) }}"
alt="thumbnail"
style="width: 48px; height: 48px; object-fit: cover; margin-right: 10px; border-radius: 4px;"
onerror="this.style.display='none';">
<p class="mb-0"><strong>Media Name:</strong> {{ media.file_name }}</p>
</div>

View File

@@ -130,7 +130,7 @@ def add_player(username, hostname, password, quickconnect_password, orientation=
log_player_created(username, hostname)
return new_player
def edit_player(player_id, username, hostname, password=None, quickconnect_password=None):
def edit_player(player_id, username, hostname, password=None, quickconnect_password=None, orientation=None):
"""
Edit an existing player's details.
"""
@@ -147,6 +147,9 @@ def edit_player(player_id, username, hostname, password=None, quickconnect_passw
if quickconnect_password:
player.quickconnect_password = bcrypt.generate_password_hash(quickconnect_password).decode('utf-8')
if orientation:
player.orientation = orientation
db.session.commit()
log_player_edited(username)
return player

View File

@@ -105,23 +105,14 @@ def convert_video_and_update_playlist(app, file_path, original_filename, target_
print(f"Video conversion failed for: {file_path}")
# PDF conversion functions
def convert_pdf_to_images(pdf_file, output_folder, delete_pdf=True):
def convert_pdf_to_images(pdf_file, output_folder, delete_pdf=True, dpi=600):
"""
Convert a PDF file to images in sequential order.
Args:
pdf_file (str): Path to the PDF file
output_folder (str): Path to save the images
delete_pdf (bool): Whether to delete the PDF file after processing
Returns:
list: List of generated image filenames in page order, or empty list if conversion failed
Convert a PDF file to images in sequential order at high resolution (4K).
"""
print(f"Converting PDF to images: {pdf_file}")
print(f"Converting PDF to images: {pdf_file} at {dpi} DPI")
try:
# Convert PDF to images
images = convert_from_path(pdf_file, dpi=300)
print(f"Number of pages in PDF: {len(images)}")
images = convert_from_path(pdf_file, dpi=dpi)
base_name = os.path.splitext(os.path.basename(pdf_file))[0]
image_filenames = []
@@ -240,6 +231,7 @@ def process_pptx(input_file, output_folder, duration, target_type, target_id):
'--headless',
'--convert-to', 'pdf',
'--outdir', output_folder,
'--printer-resolution', '600',
input_file
]
@@ -251,7 +243,7 @@ def process_pptx(input_file, output_folder, duration, target_type, target_id):
print(f"LibreOffice errors (if any): {result.stderr.decode()}")
# Step 2: Convert PDF to images and update playlist
image_filenames = convert_pdf_to_images(pdf_file, output_folder, True)
image_filenames = convert_pdf_to_images(pdf_file, output_folder, True, dpi=600)
# Verify we got images
if not image_filenames:
@@ -306,7 +298,7 @@ def process_uploaded_files(app, files, media_type, duration, target_type, target
if media_type == 'image':
add_image_to_playlist(app, file, filename, duration, target_type, target_id)
result['message'] = f"Image {filename} added to playlist"
log_upload('image', filename, target_type, target_name)
log_upload('image', filename, target_type, target_id)
elif media_type == 'video':
# For videos, add to playlist then start conversion in background
@@ -329,7 +321,7 @@ def process_uploaded_files(app, files, media_type, duration, target_type, target
threading.Thread(target=convert_video_and_update_playlist,
args=(app, file_path, filename, target_type, target_id, duration)).start()
result['message'] = f"Video {filename} added to playlist and being processed"
log_upload('video', filename, target_type, target_name)
log_upload('video', filename, target_type, target_id)
elif media_type == 'pdf':
# For PDFs, convert to images and update playlist
@@ -337,7 +329,7 @@ def process_uploaded_files(app, files, media_type, duration, target_type, target
duration, target_type, target_id)
if success:
result['message'] = f"PDF {filename} processed successfully"
log_process('pdf', filename, target_type, target_name)
log_process('pdf', filename, target_type, target_id)
else:
result['success'] = False
result['message'] = f"Error processing PDF file: {filename}"
@@ -348,7 +340,7 @@ def process_uploaded_files(app, files, media_type, duration, target_type, target
duration, target_type, target_id)
if success:
result['message'] = f"PowerPoint {filename} processed successfully"
log_process('ppt', filename, target_type, target_name)
log_process('ppt', filename, target_type, target_id)
else:
result['success'] = False
result['message'] = f"Error processing PowerPoint file: {filename}"