Recherche avancée

Médias (0)

Mot : - Tags -/interaction

Aucun média correspondant à vos critères n’est disponible sur le site.

Autres articles (50)

  • Dépôt de média et thèmes par FTP

    31 mai 2013, par

    L’outil MédiaSPIP traite aussi les média transférés par la voie FTP. Si vous préférez déposer par cette voie, récupérez les identifiants d’accès vers votre site MédiaSPIP et utilisez votre client FTP favori.
    Vous trouverez dès le départ les dossiers suivants dans votre espace FTP : config/ : dossier de configuration du site IMG/ : dossier des média déjà traités et en ligne sur le site local/ : répertoire cache du site web themes/ : les thèmes ou les feuilles de style personnalisées tmp/ : dossier de travail (...)

  • Selection of projects using MediaSPIP

    2 mai 2011, par

    The examples below are representative elements of MediaSPIP specific uses for specific projects.
    MediaSPIP farm @ Infini
    The non profit organizationInfini develops hospitality activities, internet access point, training, realizing innovative projects in the field of information and communication technologies and Communication, and hosting of websites. It plays a unique and prominent role in the Brest (France) area, at the national level, among the half-dozen such association. Its members (...)

  • Encodage et transformation en formats lisibles sur Internet

    10 avril 2011

    MediaSPIP transforme et ré-encode les documents mis en ligne afin de les rendre lisibles sur Internet et automatiquement utilisables sans intervention du créateur de contenu.
    Les vidéos sont automatiquement encodées dans les formats supportés par HTML5 : MP4, Ogv et WebM. La version "MP4" est également utilisée pour le lecteur flash de secours nécessaire aux anciens navigateurs.
    Les documents audios sont également ré-encodés dans les deux formats utilisables par HTML5 :MP3 et Ogg. La version "MP3" (...)

Sur d’autres sites (7449)

  • How can I open a program using PYTHON with Mutliprocessing, and send it strings from the main process ?

    12 février 2018, par Just Askin

    I have a program that sends frames as strings to FFMPEG using something similar to :

    Working script that streams without using multiprocessing module currently on Ubuntu

    #!/usr/bin/python
    import sys, os
    import subprocess as sp
    import pygame
    from pygame.locals import QUIT, KEYUP, K_ESCAPE
    import pygame.display

    pygame.init()
    os.environ['SDL_VIDEODRIVER'] = 'dummy'
    pygame.display.init()
    Display_Surface = pygame.display.set_mode([1280,720], 0, 32)

    # FFMPEG command and settings
    command = ['ffmpeg', '-framerate', '25', '-s', '1280x720', '-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
              '-f', 'lavfi', '-i', 'anullsrc=cl=mono',
              '-pix_fmt', 'yuv420p','-s', 'hd720', '-r', '25', '-g', '50',
              '-f', 'flv', 'rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx']

    pipe = sp.Popen(command, bufsize=0, stdin=sp.PIPE)

    while True:
       # Quit event handling
       for event in pygame.event.get():
           if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
               pygame.quit()
               sys.exit()

       pipe.stdin.write(pygame.image.tostring(Display_Surface, "RGBA"))

    pipe.stdin.close()
    pygame.display.quit()
    os._exit()

    This works fine, except for the fact that it is killing my CPU, which in turn causes my live stream to freeze often. The stupid GIL won’t let FFMPEG run on another CPU/Core while I have 3 perfectly good cores doing nothing.

    I just whipped up some code to open FFMPEG in another process. (By the way, I’m familiar with threading.Thread, but not Multiprocessing).

    import os
    import subprocess as sp
    import multiprocessing

    class FFMPEG_Consumer():

       def __init__(self):
           proc = multiprocessing.Process(target=self.start_ffmpeg)
           proc.start()

       def start_ffmpeg(self):
           command = ['ffmpeg','-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
                      '-f, 'lavfi', '-i', 'anullsrc=channel_layout=stereo:sample_rate=44100',
                      '-pix_fmt', 'yuv420p','-s', 'hd720', '-f', 'flv', 'rtmp://example.com']

           pipe = sp.Popen(command, bufsize=-1, stdin=sp.PIPE)

       def send_down_the_pipe(self, frame):
           pipe.stdin.write(frame)

    ffmpeg = FFMPEG_Consumer()

    For anyone that knows how to use multiprocessing, I’m sure you will immediately see that this does not work because I can’t share variables this way across processes. But, it does open FFMPEG on another core.

    Most online tutorials and resources focus creating pools of workers and queues to send those workers something to be processed until a job is finished. I am however trying to send a new string repeatedly to FFMPEG through each iteration.

    How can I pipe my string to that process/instance of FFMPEG ?

    Or is what I’m trying to do not possible ?

    This was the working solution (with dumbed down FFMPEG settings) :

    #!/usr/bin/python
    import sys, os, multiprocessing
    import subprocess as sp
    import pygame
    from pygame.locals import QUIT, KEYUP, K_ESCAPE
    import pygame.display

    pygame.init()
    os.environ['SDL_VIDEODRIVER'] = 'dummy'
    pygame.display.init()
    Display_Surface = pygame.display.set_mode([1280,720], 0, 32)

    class FFMPEGConsumer(object):
       def __init__(self):
           self._r, self._w = multiprocessing.Pipe()
           self.reader = os.fdopen(self._r.fileno(), 'r')
           self.writer = os.fdopen(self._w.fileno(), 'w', 0)
           self.proc = None

       def start_ffmpeg(self):

           command = ['ffmpeg', '-framerate', '25', '-s', '1280x720', '-pix_fmt', 'rgba', '-f', 'rawvideo', '-i', '-',
              '-f', 'lavfi', '-i', 'anullsrc=cl=mono',
              '-pix_fmt', 'yuv420p','-s', 'hd720', '-r', '25', '-g', '50',
              '-f', 'flv', 'rtmp://a.rtmp.youtube.com/live2/xxxx-xxxx-xxxx-xxxx']

           self.proc = sp.Popen(command, bufsize=-1, stdin=self.reader)

       def send_down_the_pipe(self, frame):
           self.writer.write(frame)
           #print self._stdin.read()

       def __del__(self):
           self.reader.close()
           self.writer.close()

    ffmpeg = FFMPEGConsumer()

    while True:
       # Quit event handling
       for event in pygame.event.get():
           if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
               pygame.quit()
               sys.exit()

       ffmpeg.send_down_the_pipe(pygame.image.tostring(Display_Surface, "RGBA"))
       proc.join()

    pipe.stdin.close()
    pygame.display.quit()
    os._exit()

    All cores are firing and no lags so far !!!

  • [ffmpeg][asyncio] main process is held by ffmpeg command

    5 octobre 2024, par Michael Lopez

    I created a python program for handling my Arlo Camera. To do that I have been using the pyaarlo library (https://github.com/twrecked/pyaarlo) to catch camera's events.
The goal is to monitor if there is an active stream on cameras, get the RTSP stream url and reStream it to a HLS playlist for local usage.

    


    Here the python code :

    


    import asyncio
from decouple import config
import logging
from my_pyaarlo import PyArlo
import urllib.parse
from queue import Queue
import signal

# Read config from ENV (unchanged)
ARLO_USER = config('ARLO_USER')
ARLO_PASS = config('ARLO_PASS')
IMAP_HOST = config('IMAP_HOST')
IMAP_USER = config('IMAP_USER')
IMAP_PASS = config('IMAP_PASS')
DEBUG = config('DEBUG', default=False, cast=bool)
PYAARLO_BACKEND = config('PYAARLO_BACKEND', default=None)
PYAARLO_REFRESH_DEVICES = config('PYAARLO_REFRESH_DEVICES', default=0, cast=int)
PYAARLO_STREAM_TIMEOUT = config('PYAARLO_STREAM_TIMEOUT', default=0, cast=int)
PYAARLO_STORAGE_DIR = config('PYAARLO_STORAGE_DIR', default=None)
PYAARLO_ECDH_CURVE = config('PYAARLO_ECDH_CURVE', default=None)

# Initialize logging
logging.basicConfig(
    level=logging.DEBUG if DEBUG else logging.INFO,
    format='%(asctime)s [%(levelname)s] %(name)s: %(message)s'
)
logger = logging.getLogger(__name__)

ffmpeg_processes = {}
event_queue = Queue()
shutdown_event = asyncio.Event()

async def handle_idle_event(camera):
    logger.info(f"Idle event detected for camera: {camera.name}")
    await stop_ffmpeg_stream(camera.name)

async def get_stream_url(camera):
    try:
        # Attempt to get the stream URL
        stream_url = await asyncio.to_thread(camera.get_stream()
        if stream_url:
            return stream_url
        else:
            logger.warning(f"Unable to get stream URL for {camera.name}. Stream might not be active.")
            return None
    except Exception as e:
        logger.error(f"Error getting stream URL for {camera.name}: {e}")
        return None

async def handle_user_stream_active_event(camera):
    logger.info(f"User stream active event detected for camera: {camera.name}")

    # Get the stream URL
    stream_url = await get_stream_url(camera)
    if stream_url:
        logger.info(f"Stream URL for {camera.name}: {stream_url}")
        await start_ffmpeg_stream(camera.name, stream_url)
    else:
        logger.warning(f"No stream URL available for {camera.name}")

async def event_handler(device, attr, value):
    logger.debug(f"Event: {device.name}, Attribute: {attr}, Value: {value}")
    if attr == 'activityState':
        if value == 'idle':
            await handle_idle_event(device)
        elif value in ['userStreamActive']:
            await handle_user_stream_active_event(device)
    elif attr == 'mediaUploadNotification':
        logger.info(f"Media uploaded for camera: {device.name}")

def sync_event_handler(device, attr, value):
    # This function will be called by PyArlo's synchronous callbacks
    event_queue.put((device, attr, value))

async def process_event_queue():
    while not shutdown_event.is_set():
        try:
            if not event_queue.empty():
                device, attr, value = event_queue.get()
                await event_handler(device, attr, value)
            await asyncio.sleep(0.1)  # Small delay to prevent busy-waiting
        except asyncio.CancelledError:
            break
        except Exception as e:
            logger.error(f"Error processing event: {e}")

async def display_status(arlo):
    while not shutdown_event.is_set():
        print("\n--- Camera Statuses ---")
        for camera in arlo.cameras:
            print(f"{camera.name}: {camera.state}")
        print("------------------------")
        await asyncio.sleep(5)

async def start_ffmpeg_stream(camera_name, stream_url):
    if camera_name not in ffmpeg_processes:
        output_hls = f"/tmp/{camera_name}.m3u8"

        try:
            new_url = urllib.parse.quote(stream_url.encode(), safe=':/?&=')
            logger.info(f"NEW_URL: {new_url}")

            ffmpeg_cmd = [
                "ffmpeg", "-hide_banner", "-loglevel", "quiet", "-nostats", "-nostdin", "-y", "-re",
                "-i", new_url,
                "-c:v", "libx264", "-preset", "veryfast",
                "-an", "-sn",
                "-f", "hls", "-hls_time", "4", "-hls_list_size", "10",
                "-hls_flags", "delete_segments", output_hls,
            ]
            logger.info(f"Starting FFmpeg command: {ffmpeg_cmd}")
            
            process = await asyncio.create_subprocess_exec(
                *ffmpeg_cmd,
                stdout=asyncio.subprocess.DEVNULL,
                stderr=asyncio.subprocess.DEVNULL
            )
            ffmpeg_processes[camera_name] = process
            logger.info(f"Started ffmpeg process with PID: {process.pid}")

        except Exception as e:
            logger.error(f"Error starting FFmpeg for {camera_name}: {e}")

async def stop_ffmpeg_stream(camera_name):
    logger.info(f"Stopping ffmpeg process for {camera_name}")
    ffmpeg_process = ffmpeg_processes.pop(camera_name, None)
    if ffmpeg_process:
        ffmpeg_process.terminate()

        try:
            await ffmpeg_process.wait()
            logger.info(f"{camera_name} stopped successfully")
        except Exception as e:
            print(f"FFMPEG Process didn't stop in time, forcefully terminating: {e}")
            ffmpeg_process.kill()
    else:
        logger.info(f"FFmpeg process for {camera_name} already stopped")

async def shutdown(signal, loop):
    logger.info(f"Received exit signal {signal.name}...")
    shutdown_event.set()
    tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
    [task.cancel() for task in tasks]
    logger.info(f"Cancelling {len(tasks)} outstanding tasks")
    await asyncio.gather(*tasks, return_exceptions=True)
    loop.stop()

async def main():
    # Initialize PyArlo
    arlo_args = {
        'username': ARLO_USER,
        'password': ARLO_PASS,
        'tfa_source': 'imap',
        'tfa_type': 'email',
        'tfa_host': IMAP_HOST,
        'tfa_username': IMAP_USER,
        'tfa_password': IMAP_PASS,
        'save_session': True,
        'verbose_debug': DEBUG
    }

    # Add optional arguments
    for arg, value in [
        ('refresh_devices_every', PYAARLO_REFRESH_DEVICES),
        ('stream_timeout', PYAARLO_STREAM_TIMEOUT),
        ('backend', PYAARLO_BACKEND),
        ('storage_dir', PYAARLO_STORAGE_DIR),
        ('ecdh_curve', PYAARLO_ECDH_CURVE)
    ]:
        if value:
            arlo_args[arg] = value
    
    try:
        arlo = await asyncio.to_thread(PyArlo, **arlo_args)
    except Exception as e:
        logger.error(f"Failed to initialize PyArlo: {e}")
        return

    logger.info("Connected to Arlo. Monitoring events...")

    # Register event handlers for each camera
    for camera in arlo.cameras:
        camera.add_attr_callback('*', sync_event_handler)

    # Start the status display task
    status_task = asyncio.create_task(display_status(arlo))

    # Start the event processing task
    event_processing_task = asyncio.create_task(process_event_queue())

    # Set up signal handlers
    loop = asyncio.get_running_loop()
    for s in (signal.SIGHUP, signal.SIGTERM, signal.SIGINT):
        loop.add_signal_handler(
            s, lambda s=s: asyncio.create_task(shutdown(s, loop)))

    try:
        # Keep the main coroutine running
        while not shutdown_event.is_set():
            try:
                await asyncio.sleep(1)
            except asyncio.CancelledError:
                break
    except Exception as e:
        logger.error(f"Unexpected error in main loop: {e}")
    finally:
        logger.info("Shutting down...")
        for camera_name in list(ffmpeg_processes.keys()):
            await stop_ffmpeg_stream(camera_name)
        
        # Cancel and wait for all tasks
        tasks = [status_task, event_processing_task]
        for task in tasks:
            if not task.done():
                task.cancel()
        await asyncio.gather(*tasks, return_exceptions=True)
        
        logger.info("Program terminated.")

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        logger.info("Keyboard interrupt received. Exiting.")
    except Exception as e:
        logger.error(f"Unhandled exception: {e}")
    finally:
        logger.info("Program exit complete.")


    


    My issue is about the ffmpeg command which is hold the main process (or the event loop) when it runs, blocking the events coming from the pyaarlo library. The state of the camera continues to work with the good information.

    


    I tried lot of things, without asyncio, with multiprocessing, with subprocess, ... the behavior is always the same. In some cases, I received the idle event after the key interrupt.

    


    Another information :

    


      

    • When I stop the active stream, the event is not received but when I start the stream just after, that event is received.
    • 


    • When I run the same ffmpeg command but with a local long video file, everything is Ok. So, it why I guess that the ffmpeg command is impacting the main process.
    • 


    


    I succedeed in running the ffmpeg command with rtsp url stream but without a loop event monitoring :

    


    import asyncio
import signal
import sys
import os

async def run_infinite_command():
    # Start a simple HTTP server as our "infinite" command
    url = "rstp://localhost:8554/camera1/stream" # it is a fake url
    ffmpeg_cmd = [
        "ffmpeg", "-re", "-i", url,
        "-c:v", "libx264", "-preset", "veryfast",
        "-c:a", "copy",
        "-f", "hls", "-hls_time", "4", "-hls_list_size", "10",
        "-hls_flags", "delete_segments", "/tmp/output.m3u8"
    ]
    
    process = await asyncio.create_subprocess_exec(
        *ffmpeg_cmd,
        stdout=asyncio.subprocess.DEVNULL,
        stderr=asyncio.subprocess.DEVNULL
    )
    
    print(f"Started HTTP server with PID: {process.pid}")
    return process

async def main():
    # Start the infinite command
    process = await run_infinite_command()

    # Run the main loop for a few seconds
    for i in range(10):
        print(f"Main loop iteration {i+1}")
        await asyncio.sleep(1)

    # Stop the infinite command
    print("Stopping the HTTP server...")
    if sys.platform == "win32":
        # On Windows, we need to use CTRL_C_EVENT
        os.kill(process.pid, signal.CTRL_C_EVENT)
    else:
        # On Unix-like systems, we can use SIGTERM
        process.send_signal(signal.SIGTERM)

    # Wait for the process to finish
    try:
        await asyncio.wait_for(process.wait(), timeout=5.0)
        print("HTTP server stopped successfully")
    except asyncio.TimeoutError:
        print("HTTP server didn't stop in time, forcefully terminating")
        process.kill()

    print("Program finished")

if __name__ == "__main__":
    asyncio.run(main())


    


    With this script, the ffmpeg command is correctly launched and terminated after the for loop.

    


    Could you help ?

    


  • Flash block/timeout handling improvements. Cleaner CSS, updated demo and main demos include handling now

    20 mars 2010, par Scott Schiller

    m demo/360-player/360player.css m demo/360-player/canvas-visualization-basic.html m demo/360-player/canvas-visualization.html m demo/360-player/index.html m demo/api/index.html + demo/flashblock/flashblock.css m demo/flashblock/index.html m demo/index.css m (...)