Membuat Aplikasi Streaming Video ke YouTube dengan Python dan Flask

Pinterest LinkedIn Tumblr +

Dalam artikel ini, kita akan membahas cara membuat aplikasi sederhana yang memungkinkan kita untuk streaming video ke YouTube menggunakan Python, Flask, dan ffmpeg. Aplikasi ini akan memungkinkan pengguna untuk mengunggah video dan kemudian men-streaming-nya langsung ke platform YouTube melalui RTMP (Real-Time Messaging Protocol).

Persiapan Awal

Sebelum masuk ke penjelasan kode, pastikan Anda sudah memiliki beberapa software dan library berikut:

  1. Python 3.x: Pastikan Python sudah terinstall di komputer Anda.
  2. Pip: Pengelola paket Python, pastikan sudah ada dengan mengetik pip –version di terminal.
  3. ffmpeg: Digunakan untuk encoding dan streaming video. Untuk instalasi, Anda bisa mengunduh dari situs resmi ffmpeg dan ikuti instruksinya.
  4. Flask: Web framework yang kita gunakan untuk membuat server sederhana. Instal Flask dengan perintah:
  5. pip install flask
    
  6. Threading: Digunakan untuk menjalankan streaming video dalam thread terpisah, agar proses server utama tidak terganggu.

Struktur Folder

Sebelum kita lanjutkan, buatlah struktur folder sederhana sebagai berikut:

project-folder/
│
├── app.py
├── templates/
│   ├── base.html
│   ├── index.html
│   └── streams.html
└── uploads/

Folder uploads/ akan digunakan untuk menyimpan file video yang diunggah. Folder templates/ akan berisi file HTML untuk tampilan web.

Penjelasan Kode app.py

Berikut adalah kode untuk file app.py, yang merupakan server Flask dan logika utama aplikasi kita.

import threading
import subprocess
import os
from flask import Flask, render_template, request, redirect, url_for, jsonify

app = Flask(__name__)

# Path to store uploaded videos
UPLOAD_FOLDER = 'uploads/'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# Ensure the upload folder exists
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)

class CustomThread(threading.Thread):
    def __init__(self, thread_id, video_path, youtube_url, stop_event):
        threading.Thread.__init__(self)
        self.thread_id = thread_id
        self.video_path = video_path
        self.youtube_url = youtube_url
        self.stop_event = stop_event
        self.repeat = True

    def stream_to_youtube(self):
        # ffmpeg command to stream the video to YouTube
        video_path = self.video_path.replace('\\', '/')
        command = [
            'ffmpeg',
            '-re',  # Read input at native frame rate
            '-i', video_path,  # Input file
            '-c:v', 'libx264',  # Video codec
            '-preset', 'veryfast',  # Encoding speed
            '-maxrate', '3000k',  # Max bitrate
            '-bufsize', '6000k',  # Buffer size
            '-pix_fmt', 'yuv420p',  # Pixel format
            '-g', '50',  # Group of picture size (keyframes)
            '-c:a', 'aac',  # Audio codec
            '-b:a', '160k',  # Audio bitrate
            '-f', 'flv',  # Output format for RTMP streaming
            self.youtube_url
        ]
        if self.repeat:
            command.insert(1, '-stream_loop')
            command.insert(2, '-1')

        # Start the ffmpeg process
        if subprocess.Popen(command):
            return True
        else:
            return False

    def run(self):
        self.stream_to_youtube()
    
    def stop(self):
        self.stop_event.set()

stream_threads = []

@app.route('/')
def index():
    global stream_threads
    if len(stream_threads) > 0:
        print(stream_threads[0].thread_id)
    return render_template('index.html')

@app.route('/upload', methods=['POST'])
def upload_video():
    global stream_threads
    # Get the uploaded video and stream key from the form
    video = request.files['video']
    stream_key = request.form['stream_key']

    if video and stream_key:
        # Save the uploaded video file
        video_path = os.path.join(app.config['UPLOAD_FOLDER'], video.filename).replace('\\', '/')
        video.save(video_path)

        # Stream the video to YouTube using the stream key
        youtube_url = f"rtmp://a.rtmp.youtube.com/live2/{stream_key}"

        # Start a new thread to stream the video
        stop_event = threading.Event()
        thread_id = len(stream_threads) + 1
        stream_thread = CustomThread(thread_id, video_path, youtube_url, stop_event)
        stream_threads.append(stream_thread)
        stream_thread.run()

        return f"Video streaming to YouTube started with thread ID !"
    else:
        return "Please upload a video and provide a stream key."

@app.route('/stop_all_streams', methods=['POST'])
def stop_all_streams():
    global stream_threads
    for stream_thread in stream_threads:
        stream_thread.stop()
    return "All streaming threads stopped!"

# streams
@app.route('/streams')
def streams():
    global stream_threads
    return render_template('streams.html', stream_threads=stream_threads)

@app.route('/stop_stream/<int:thread_id>', methods=['POST'])
def stop_stream(thread_id):
    global stream_threads
    for stream_thread in stream_threads:
        if stream_thread.thread_id == thread_id:
            stream_thread.stop()
            stream_threads.remove(stream_thread)
            return f"Stream {thread_id} stopped!"
    return f"Stream {thread_id} not found!"

if __name__ == '__main__':
    app.run(debug=True)

Penjelasan Kode

  1. Library yang Digunakan:
    • threading: Menjalankan proses streaming dalam thread terpisah.
    • subprocess: Digunakan untuk menjalankan ffmpeg.
    • os: Mengatur path dan file.
    • flask: Framework untuk membuat server web.
  2. CustomThread: Kelas ini bertanggung jawab untuk menjalankan streaming video menggunakan ffmpeg. Kode ini memulai thread yang mengambil video dari path lokal dan mengirimkannya ke URL RTMP YouTube.
  3. Endpoint Utama:
    • / (Homepage): Halaman utama untuk mengunggah video dan memulai stream.
    • /upload: Endpoint untuk menangani unggahan video dan memulai streaming.
    • /stop_all_streams: Endpoint untuk menghentikan semua stream yang sedang berjalan.
    • /streams: Menampilkan semua stream yang sedang aktif.
    • /stop_stream/<thread_id>: Menghentikan stream berdasarkan thread_id.
BACA JUGA  8 Rahasia Membuat Judul Artikel yang Memikat Perhatian Pembaca

Tampilan HTML (Folder templates/)

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Video Streaming</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/3.1.0/css/adminlte.min.css">
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        .container {
            margin-top: 20px;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <a class="navbar-brand" href="/">Video Streaming</a>
    </nav>

    <div class="container-fluid">
        <div class="row">
            <nav class="col-md-2 d-none d-md-block bg-light sidebar">
                <div class="sidebar-sticky">
                    <ul class="nav flex-column">
                        <li class="nav-item">
                            <a class="nav-link" href="/">Stream to YouTube</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="/streams">Active Streams</a>
                        </li>
                    </ul>
                </div>
            </nav>
        </div>
    </div>

    <div class="container">
        {% block content %}{% endblock %}
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/3.1.0/js/adminlte.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</body>
</html>

index.html

{% extends 'base.html' %}

{% block content %}
    <h1>Stream to YouTube</h1>
    <form action="{{ url_for('upload_video') }}" method="POST" enctype="multipart/form-data">
        <label for="video">Upload Video:</label>
        <input type="file" name="video" id="video" required><br><br>
        
        <label for="stream_key">YouTube Stream Key:</label>
        <input type="text" name="stream_key" id="stream_key" required><br><br>
        
        <button type="submit">Start Streaming</button>
    </form>
    <hr>

    <h2>Active Streams</h2>
    <ul>
        {% for stream_id in streams %}
            <li>Stream ID: {{ stream_id }} 
                <form action="/stop_stream/{{ stream_id }}" method="post" style="display:inline;">
                    <button type="submit">Stop Stream</button>
                </form>
            </li>
        {% else %}
            <li>No active streams.</li>
        {% endfor %}
    </ul>
{% endblock %}

streams.html

{% extends "base.html" %}

{% block content %}
    <h1>Active Streams</h1>
    {{ streams }}
    <ul>
        <!-- {% for stream_id in streams %}
            <li>Stream ID: {{ stream_id.thread_id }} 
                <form action="/stop_stream/{{ stream_id.thread_id }}" method="post" style="display:inline;">
                    <button type="submit">Stop Stream</button>
                </form>
            </li>
        {% else %}
            <li>No active streams.</li>
        {% endfor %} -->
    </ul>
    <a href="/">Back to Home</a>
{% endblock %}

Menjalankan Aplikasi

  1. Simpan file-file di atas ke dalam struktur folder yang telah dijelaskan.
  2. Buka terminal, navigasikan ke direktori proyek, dan jalankan server Flask dengan perintah:
  3. python app.py
    
  4. Buka browser dan akses http://localhost:5000.
BACA JUGA  Vanilla CSS vs Bootstrap vs Tailwind: Mana yang Tepat untuk Kamu?

Dengan langkah-langkah di atas, aplikasi ini memungkinkan pengguna untuk mengunggah video dan men-streaming-nya ke YouTube secara langsung. Anda juga bisa melihat dan menghentikan stream aktif dari halaman yang telah disediakan.

Share.

About Author

I am a Full-Stack Developer who loves to translate designs files into Website and Application, Based in Bandar Lampung - Indonesia

Comments are closed.