基于Flask的带内置视频播放器网站:用户使用时长限制方案咨询
Great question! Your initial idea of adding a credits_minutes field to the user profile is solid—it’s the foundation for most time-based access control systems. Below’s a step-by-step breakdown of how to implement this effectively in your Flask app, along with safeguards to prevent abuse.
Core Approach: Track & Deduct Playback Minutes
The core flow will be:
- Each user has a
credits_minutesvalue stored in their database record (e.g., 60 for 1 hour of access). - When a user watches a video, track the actual time they spend playing it (not just the video duration—since they might pause/skip).
- Deduct the elapsed time from their
credits_minutesin real-time or at intervals. - Block video access once
credits_minutesdrops to 0 (or below).
Key Implementation Steps
1. Update Your User Model
First, add the credits_minutes field to your User model (assuming you’re using SQLAlchemy, a common choice with Flask):
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password_hash = db.Column(db.String(120), nullable=False) credits_minutes = db.Column(db.Integer, default=0) # Set default to 0, update on signup/purchase
2. Track Playback Time (Frontend + Backend)
You can’t rely solely on the frontend to report playback time—users could tamper with it. Instead, use a combination of frontend tracking and backend validation:
Frontend (JavaScript)
Use the HTML5 video element’s events to send periodic updates to your Flask backend. For example, send a request every 30 seconds with the elapsed play time:
const video = document.getElementById('video-player'); let startTime = null; let lastReportedTime = 0; video.addEventListener('play', () => { startTime = Date.now(); setInterval(() => { if (!video.paused) { const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000) - lastReportedTime; if (elapsedSeconds >= 30) { // Send update every 30 seconds fetch('/api/deduct-credits', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ seconds: elapsedSeconds }) }) .then(response => response.json()) .then(data => { if (data.remaining <= 0) { video.pause(); alert('Your access credits have expired.'); } lastReportedTime += elapsedSeconds; }); } } }, 1000); });
Backend (Flask Route)
Create a protected route to handle credit deductions. Validate the user is logged in, then update their credits_minutes:
from flask import request, jsonify, login_required from flask_login import current_user @app.route('/api/deduct-credits', methods=['POST']) @login_required def deduct_credits(): data = request.get_json() seconds_used = data.get('seconds', 0) if seconds_used <= 0: return jsonify({'error': 'Invalid time value'}), 400 # Convert seconds to minutes (round up to avoid giving free time) minutes_used = (seconds_used + 59) // 60 # Update user credits (ensure we don't go negative) current_user.credits_minutes = max(current_user.credits_minutes - minutes_used, 0) db.session.commit() return jsonify({ 'remaining': current_user.credits_minutes, 'used': minutes_used })
3. Enforce Access Restrictions
Before allowing a user to load a video, check their remaining credits in the route that serves the video page or video file:
@app.route('/video/<int:video_id>') @login_required def view_video(video_id): if current_user.credits_minutes <= 0: return "Your access credits have expired. Please purchase more to continue.", 403 # Fetch video details and render the page video = Video.query.get_or_404(video_id) return render_template('video.html', video=video)
Bonus Tips to Prevent Abuse & Improve UX
- Server-Side Validation: Never trust frontend reports entirely. Store the start time on the server when the user begins playing, then calculate elapsed time when they stop or send updates to cross-check.
- Handle Pauses/Stops: Add event listeners for
pauseandendedevents to send a final update with the total elapsed time. - Expire Credits Over Time: If credits have an expiration date, add an
credits_expiry_datefield to the User model and check it alongsidecredits_minutes. - Show Remaining Time: Display the user’s remaining credits in the navbar or video player so they know how much time they have left.
- Batch Deductions: Instead of deducting every second, batch updates every 30-60 seconds to reduce server load.
Alternative: Session-Based Time Tracking
If you don’t need persistent credits (e.g., limited access per session), you could track time spent in the user’s session. But your initial credits_minutes approach is better for long-term access control.
内容的提问来源于stack exchange,提问作者Ilja Leiko

