Recherche avancée

Médias (1)

Mot : - Tags -/biographie

Autres articles (88)

  • MediaSPIP 0.1 Beta version

    25 avril 2011, par

    MediaSPIP 0.1 beta is the first version of MediaSPIP proclaimed as "usable".
    The zip file provided here only contains the sources of MediaSPIP in its standalone version.
    To get a working installation, you must manually install all-software dependencies on the server.
    If you want to use this archive for an installation in "farm mode", you will also need to proceed to other manual (...)

  • Le profil des utilisateurs

    12 avril 2011, par

    Chaque utilisateur dispose d’une page de profil lui permettant de modifier ses informations personnelle. Dans le menu de haut de page par défaut, un élément de menu est automatiquement créé à l’initialisation de MediaSPIP, visible uniquement si le visiteur est identifié sur le site.
    L’utilisateur a accès à la modification de profil depuis sa page auteur, un lien dans la navigation "Modifier votre profil" est (...)

  • Configurer la prise en compte des langues

    15 novembre 2010, par

    Accéder à la configuration et ajouter des langues prises en compte
    Afin de configurer la prise en compte de nouvelles langues, il est nécessaire de se rendre dans la partie "Administrer" du site.
    De là, dans le menu de navigation, vous pouvez accéder à une partie "Gestion des langues" permettant d’activer la prise en compte de nouvelles langues.
    Chaque nouvelle langue ajoutée reste désactivable tant qu’aucun objet n’est créé dans cette langue. Dans ce cas, elle devient grisée dans la configuration et (...)

Sur d’autres sites (8440)

  • How to Turn image A + audio + A into Video A with the exact same attributes of Video B so both can be concatenated without encoding [closed]

    13 décembre 2024, par Furkan Gözükara

    I have image A and it is PNG

    


    I have audio A and it is MP3

    


    I have video B that can be any format, resolution, encoding, audio, etc

    


    Now I want to turn image A + audio A into video A with the exact attributes of video B so that I can concatenate them without encoding

    


    Here my so far code which is failing. I am using Python and latest version of FFMPEG with most codecs and features

    


    def get_video_info(video_path):
    cmd = [
        FFPROBE_PATH,
        '-v', 'quiet',
        '-print_format', 'json',
        '-show_format',
        '-show_streams',
        video_path
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    info = json.loads(result.stdout)
    
    video_stream = next((s for s in info['streams'] if s['codec_type'] == 'video'), None)
    audio_stream = next((s for s in info['streams'] if s['codec_type'] == 'audio'), None)
    
    if not video_stream or not audio_stream:
        logging.error("Failed to find video or audio stream")
        return None

    return {
        'width': int(video_stream.get('width', 0)),
        'height': int(video_stream.get('height', 0)),
        'fps': eval(video_stream.get('r_frame_rate', '30/1')),
        'video_codec': video_stream.get('codec_name', ''),
        'audio_codec': audio_stream.get('codec_name', ''),
        'audio_sample_rate': int(audio_stream.get('sample_rate', 0)),
        'audio_channels': audio_stream.get('channels', 0),
        'pixel_format': video_stream.get('pix_fmt', ''),
        'color_space': video_stream.get('color_space', ''),
        'color_transfer': video_stream.get('color_transfer', ''),
        'color_primaries': video_stream.get('color_primaries', ''),
    }

def create_thumbnail_video(thumbnail_url, video_id, video_info, duration=40):
    output_dir = os.path.abspath('downloads')
    output_path = os.path.join(output_dir, f"{video_id}_thumbnail.mp4")
    audio_path = os.path.abspath("a.mp3")

    try:
        # 1. Download and process the image
        logging.info("Downloading thumbnail image...")
        response = requests.get(thumbnail_url, timeout=30)
        response.raise_for_status()

        # Save the original image
        original_image_path = os.path.join(output_dir, f'{video_id}_original_image.png')
        with open(original_image_path, 'wb') as f:
            f.write(response.content)

        # 2. Open and resize the image
        image = Image.open(original_image_path)
        width, height = video_info['width'], video_info['height']
        image = image.resize((width, height), Image.LANCZOS)

        # Save resized image
        resized_image_path = os.path.join(output_dir, f'{video_id}_resized_image.png')
        image.save(resized_image_path, 'PNG')

        # 3. Get properties of the main video using ffprobe
        main_video_path = os.path.join(output_dir, f"{video_id}.mp4")  # Assuming main video has .mp4 extension
        main_video_info = get_video_info(main_video_path)

        if not main_video_info:
            raise Exception("Could not get information about the main video.")

        # 4. Generate video with matching encoding
        logging.info("Generating thumbnail video with matching codec and properties...")

        ffmpeg_command = [
            FFMPEG_PATH,
            '-y',
            '-loop', '1',
            '-i', resized_image_path,
            '-i', audio_path,
            '-c:v', main_video_info['video_codec'],
            '-c:a', main_video_info['audio_codec'],
            '-ar', str(main_video_info['audio_sample_rate']),
            '-pix_fmt', main_video_info['pixel_format'],
            '-color_range', main_video_info.get('color_range', '1'),  # Default to tv/mpeg (limited) if not found
            '-colorspace', main_video_info['color_space'],
            '-color_trc', main_video_info['color_transfer'],
            '-color_primaries', main_video_info['color_primaries'],
            '-vf', f"fps={main_video_info['fps']},scale={width}:{height}",
            '-shortest',
            '-t', str(duration),
            output_path
        ]

        subprocess.run(ffmpeg_command, check=True, capture_output=True, text=True)
        logging.info(f"Thumbnail video created: {output_path}")

        # 5. Clean up intermediate files
        for file_path in [original_image_path, resized_image_path]:
            if os.path.exists(file_path):
                os.remove(file_path)
                logging.info(f"Removed intermediate file: {file_path}")

        return output_path

    except requests.RequestException as e:
        logging.error(f"Error downloading thumbnail: {e}")
    except subprocess.CalledProcessError as e:
        logging.error(f"FFmpeg error: {e.stderr}")
    except Exception as e:
        logging.error(f"Error in create_thumbnail_video: {e}")
        logging.error(traceback.format_exc())

    # If we've reached this point, an error occurred
    logging.warning("Thumbnail video creation failed. Returning None.")
    return None


    


    Here example case

    


    Generated video from image + audio as below

    


    General
Complete name                  : C:\stream\downloads\hqDA0-waGwI_thumbnail.mp4
Format                         : MPEG-4
Format profile                 : Base Media
Codec ID                       : isom (isom/iso2/avc1/mp41)
File size                      : 1.50 MiB
Duration                       : 40 s 0 ms
Overall bit rate mode          : Variable
Overall bit rate               : 315 kb/s
Frame rate                     : 30.000 FPS
Writing application            : Lavf61.9.100

Video
ID                             : 1
Format                         : AVC
Format/Info                    : Advanced Video Codec
Format profile                 : High@L4
Format settings                : CABAC / 4 Ref Frames
Format settings, CABAC         : Yes
Format settings, Reference fra : 4 frames
Codec ID                       : avc1
Codec ID/Info                  : Advanced Video Coding
Duration                       : 40 s 0 ms
Bit rate                       : 179 kb/s
Width                          : 1 920 pixels
Height                         : 1 080 pixels
Display aspect ratio           : 16:9
Frame rate mode                : Constant
Frame rate                     : 30.000 FPS
Color space                    : YUV
Chroma subsampling             : 4:2:0
Bit depth                      : 8 bits
Scan type                      : Progressive
Bits/(Pixel*Frame)             : 0.003
Stream size                    : 875 KiB (57%)
Writing library                : x264 core 164
Encoding settings              : cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=34 / lookahead_threads=5 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00
Color range                    : Limited
Matrix coefficients            : BT.709
Codec configuration box        : avcC

Audio
ID                             : 2
Format                         : AAC LC
Format/Info                    : Advanced Audio Codec Low Complexity
Codec ID                       : mp4a-40-2
Duration                       : 40 s 0 ms
Source duration                : 40 s 23 ms
Source_Duration_LastFrame      : -8 ms
Bit rate mode                  : Variable
Bit rate                       : 128 kb/s
Channel(s)                     : 2 channels
Channel layout                 : L R
Sampling rate                  : 44.1 kHz
Frame rate                     : 43.066 FPS (1024 SPF)
Compression mode               : Lossy
Stream size                    : 621 KiB (40%)
Source stream size             : 621 KiB (40%)
Default                        : Yes
Alternate group                : 1


    


    Source video used to get video attributes

    


    General
Complete name                  : C:\stream\downloads\hqDA0-waGwI.mp4
Format                         : MPEG-4
Format profile                 : Base Media
Codec ID                       : isom (isom/iso2/avc1/mp41)
File size                      : 24.9 MiB
Duration                       : 1 min 36 s
Overall bit rate               : 2 171 kb/s
Frame rate                     : 30.000 FPS
Writing application            : Lavf61.9.100

Video
ID                             : 1
Format                         : AVC
Format/Info                    : Advanced Video Codec
Format profile                 : High@L4
Format settings                : CABAC / 3 Ref Frames
Format settings, CABAC         : Yes
Format settings, Reference fra : 3 frames
Codec ID                       : avc1
Codec ID/Info                  : Advanced Video Coding
Duration                       : 1 min 36 s
Bit rate                       : 2 036 kb/s
Width                          : 1 920 pixels
Height                         : 1 080 pixels
Display aspect ratio           : 16:9
Frame rate mode                : Constant
Frame rate                     : 30.000 FPS
Color space                    : YUV
Chroma subsampling             : 4:2:0
Bit depth                      : 8 bits
Scan type                      : Progressive
Bits/(Pixel*Frame)             : 0.033
Stream size                    : 23.3 MiB (94%)
Title                          : ISO Media file produced by Google Inc.
Color range                    : Limited
Color primaries                : BT.709
Transfer characteristics       : BT.709
Matrix coefficients            : BT.709
Codec configuration box        : avcC

Audio
ID                             : 2
Format                         : AAC LC
Format/Info                    : Advanced Audio Codec Low Complexity
Codec ID                       : mp4a-40-2
Duration                       : 1 min 36 s
Bit rate mode                  : Constant
Bit rate                       : 128 kb/s
Channel(s)                     : 2 channels
Channel layout                 : L R
Sampling rate                  : 44.1 kHz
Frame rate                     : 43.066 FPS (1024 SPF)
Compression mode               : Lossy
Stream size                    : 1.47 MiB (6%)
Title                          : ISO Media file produced by Google Inc.
Language                       : English
Default                        : Yes
Alternate group                : 1


    


  • fftools/ffprobe : add analyze_frames option for CC and grain detection

    8 décembre 2024, par Marth64
    fftools/ffprobe : add analyze_frames option for CC and grain detection
    

    Currently, ffprobe has two stream-level fields that do not work,
    closed_captions and film_grain).

    Their value is always 0 because ffprobe cannot access the internal
    codec properties when it is setting up its stream contexts.

    In this commit, add the new option -analyze_frames to ffprobe,
    allowing the user to read frames up to the interval they have defined
    and fill these fields based on what is exposed in AVPacketSideData.

    Additionally, in the same commit, don't write these fields to
    the output unless analyze_frames is enabled. Finally, fix the
    FATE test refs accordingly and update the docs.

    Signed-off-by : Marth64 <marth64@proxyid.net>

    • [DH] doc/ffprobe.texi
    • [DH] fftools/ffprobe.c
    • [DH] tests/ref/fate/cavs-demux
    • [DH] tests/ref/fate/concat-demuxer-extended-lavf-mxf
    • [DH] tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10
    • [DH] tests/ref/fate/concat-demuxer-simple1-lavf-mxf
    • [DH] tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10
    • [DH] tests/ref/fate/concat-demuxer-simple2-lavf-ts
    • [DH] tests/ref/fate/ffprobe_compact
    • [DH] tests/ref/fate/ffprobe_csv
    • [DH] tests/ref/fate/ffprobe_default
    • [DH] tests/ref/fate/ffprobe_flat
    • [DH] tests/ref/fate/ffprobe_ini
    • [DH] tests/ref/fate/ffprobe_json
    • [DH] tests/ref/fate/ffprobe_xml
    • [DH] tests/ref/fate/ffprobe_xsd
    • [DH] tests/ref/fate/flv-demux
    • [DH] tests/ref/fate/hapqa-extract-nosnappy-to-hapalphaonly-mov
    • [DH] tests/ref/fate/hapqa-extract-nosnappy-to-hapq-mov
    • [DH] tests/ref/fate/mov-zombie
    • [DH] tests/ref/fate/mxf-probe-applehdr10
    • [DH] tests/ref/fate/mxf-probe-d10
    • [DH] tests/ref/fate/mxf-probe-dnxhd
    • [DH] tests/ref/fate/mxf-probe-dv25
    • [DH] tests/ref/fate/mxf-probe-j2k
    • [DH] tests/ref/fate/ts-demux
    • [DH] tests/ref/fate/ts-small-demux
  • VLC dead input for RTP stream

    27 mars, par CaptainCheese

    I'm working on creating an rtp stream that's meant to display live waveform data from Pioneer prolink players. The motivation for sending this video out is to be able to receive it in a flutter frontend. I initially was just sending a base-24 encoding of the raw ARGB packed ints per frame across a Kafka topic to it but processing this data in flutter proved to be untenable and was bogging down the main UI thread. Not sure if this is the most optimal way of going about this but just trying to get anything to work if it means some speedup on the frontend. So the issue the following implementation is experiencing is that when I run vlc --rtsp-timeout=120000 --network-caching=30000 -vvvv stream_1.sdp where

    &#xA;

    % cat stream_1.sdp&#xA;v=0&#xA;o=- 0 1 IN IP4 127.0.0.1&#xA;s=RTP Stream&#xA;c=IN IP4 127.0.0.1&#xA;t=0 0&#xA;a=tool:libavformat&#xA;m=video 5007 RTP/AVP 96&#xA;a=rtpmap:96 H264/90000&#xA;

    &#xA;

    I see (among other questionable logs) the following :

    &#xA;

    [0000000144c44d10] live555 demux error: no data received in 10s, aborting&#xA;[00000001430ee2f0] main input debug: EOF reached&#xA;[0000000144b160c0] main decoder debug: killing decoder fourcc `h264&#x27;&#xA;[0000000144b160c0] main decoder debug: removing module "videotoolbox"&#xA;[0000000144b164a0] main packetizer debug: removing module "h264"&#xA;[0000000144c44d10] main demux debug: removing module "live555"&#xA;[0000000144c45bb0] main stream debug: removing module "record"&#xA;[0000000144a64960] main stream debug: removing module "cache_read"&#xA;[0000000144c29c00] main stream debug: removing module "filesystem"&#xA;[00000001430ee2f0] main input debug: Program doesn&#x27;t contain anymore ES&#xA;[0000000144806260] main playlist debug: dead input&#xA;[0000000144806260] main playlist debug: changing item without a request (current 0/1)&#xA;[0000000144806260] main playlist debug: nothing to play&#xA;[0000000142e083c0] macosx interface debug: Playback has been ended&#xA;[0000000142e083c0] macosx interface debug: Releasing IOKit system sleep blocker (37463)&#xA;

    &#xA;

    This is sort of confusing because when I run ffmpeg -protocol_whitelist file,crypto,data,rtp,udp -i stream_1.sdp -vcodec libx264 -f null -&#xA;I see a number logs about

    &#xA;

    [h264 @ 0x139304080] non-existing PPS 0 referenced&#xA;    Last message repeated 1 times&#xA;[h264 @ 0x139304080] decode_slice_header error&#xA;[h264 @ 0x139304080] no frame!&#xA;

    &#xA;

    After which I see the stream is received and I start getting telemetry on it :

    &#xA;

    Input #0, sdp, from &#x27;stream_1.sdp&#x27;:&#xA;  Metadata:&#xA;    title           : RTP Stream&#xA;  Duration: N/A, start: 0.016667, bitrate: N/A&#xA;  Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1200x200, 60 fps, 60 tbr, 90k tbn&#xA;Stream mapping:&#xA;  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))&#xA;Press [q] to stop, [?] for help&#xA;[libx264 @ 0x107f04f40] using cpu capabilities: ARMv8 NEON&#xA;[libx264 @ 0x107f04f40] profile High, level 3.1, 4:2:0, 8-bit&#xA;Output #0, null, to &#x27;pipe:&#x27;:&#xA;  Metadata:&#xA;    title           : RTP Stream&#xA;    encoder         : Lavf61.7.100&#xA;  Stream #0:0: Video: h264, yuv420p(tv, progressive), 1200x200, q=2-31, 60 fps, 60 tbn&#xA;      Metadata:&#xA;        encoder         : Lavc61.19.101 libx264&#xA;      Side data:&#xA;        cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A&#xA;[out#0/null @ 0x60000069c000] video:144KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: unknown&#xA;frame= 1404 fps= 49 q=-1.0 Lsize=N/A time=00:00:23.88 bitrate=N/A speed=0.834x&#xA;

    &#xA;

    Not sure why VLC is turning me down like some kind of Berghain bouncer that lets nobody in the entire night.

    &#xA;

    I initially tried just converting the ARGB ints to a YUV420p buffer and used this to create the Frame objects but I couldn't for the life of me figure out how to properly initialize it as the attempts I made kept spitting out garbled junk.

    &#xA;

    Please go easy on me, I've made an unhealthy habit of resolving nearly all of my coding questions by simply lurking the internet for answers but that's not really helping me solve this issue.

    &#xA;

    Here's the Java I'm working on (the meat of the rtp comms occurs within updateWaveformForPlayer()) :

    &#xA;

    package com.bugbytz.prolink;&#xA;&#xA;import org.apache.kafka.clients.producer.KafkaProducer;&#xA;import org.apache.kafka.clients.producer.Producer;&#xA;import org.apache.kafka.clients.producer.ProducerConfig;&#xA;import org.apache.kafka.clients.producer.ProducerRecord;&#xA;import org.bytedeco.ffmpeg.global.avcodec;&#xA;import org.bytedeco.ffmpeg.global.avutil;&#xA;import org.bytedeco.javacv.FFmpegFrameGrabber;&#xA;import org.bytedeco.javacv.FFmpegFrameRecorder;&#xA;import org.bytedeco.javacv.FFmpegLogCallback;&#xA;import org.bytedeco.javacv.Frame;&#xA;import org.bytedeco.javacv.FrameGrabber;&#xA;import org.deepsymmetry.beatlink.CdjStatus;&#xA;import org.deepsymmetry.beatlink.DeviceAnnouncement;&#xA;import org.deepsymmetry.beatlink.DeviceAnnouncementAdapter;&#xA;import org.deepsymmetry.beatlink.DeviceFinder;&#xA;import org.deepsymmetry.beatlink.Util;&#xA;import org.deepsymmetry.beatlink.VirtualCdj;&#xA;import org.deepsymmetry.beatlink.data.BeatGridFinder;&#xA;import org.deepsymmetry.beatlink.data.CrateDigger;&#xA;import org.deepsymmetry.beatlink.data.MetadataFinder;&#xA;import org.deepsymmetry.beatlink.data.TimeFinder;&#xA;import org.deepsymmetry.beatlink.data.WaveformDetail;&#xA;import org.deepsymmetry.beatlink.data.WaveformDetailComponent;&#xA;import org.deepsymmetry.beatlink.data.WaveformFinder;&#xA;&#xA;import java.awt.*;&#xA;import java.awt.image.BufferedImage;&#xA;import java.io.File;&#xA;import java.nio.ByteBuffer;&#xA;import java.text.DecimalFormat;&#xA;import java.util.ArrayList;&#xA;import java.util.HashMap;&#xA;import java.util.HashSet;&#xA;import java.util.Map;&#xA;import java.util.Properties;&#xA;import java.util.Set;&#xA;import java.util.concurrent.ExecutionException;&#xA;import java.util.concurrent.Executors;&#xA;import java.util.concurrent.ScheduledExecutorService;&#xA;import java.util.concurrent.ScheduledFuture;&#xA;import java.util.concurrent.TimeUnit;&#xA;&#xA;import static org.bytedeco.ffmpeg.global.avutil.AV_PIX_FMT_RGB24;&#xA;&#xA;public class App {&#xA;    public static ArrayList<track> tracks = new ArrayList&lt;>();&#xA;    public static boolean dbRead = false;&#xA;    public static Properties props = new Properties();&#xA;    private static Map recorders = new HashMap&lt;>();&#xA;    private static Map frameCount = new HashMap&lt;>();&#xA;&#xA;    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);&#xA;    private static final int FPS = 60;&#xA;    private static final int FRAME_INTERVAL_MS = 1000 / FPS;&#xA;&#xA;    private static Map schedules = new HashMap&lt;>();&#xA;&#xA;    private static Set<integer> streamingPlayers = new HashSet&lt;>();&#xA;&#xA;    public static String byteArrayToMacString(byte[] macBytes) {&#xA;        StringBuilder sb = new StringBuilder();&#xA;        for (int i = 0; i &lt; macBytes.length; i&#x2B;&#x2B;) {&#xA;            sb.append(String.format("%02X%s", macBytes[i], (i &lt; macBytes.length - 1) ? ":" : ""));&#xA;        }&#xA;        return sb.toString();&#xA;    }&#xA;&#xA;    private static void updateWaveformForPlayer(int player) throws Exception {&#xA;        Integer frame_for_player = frameCount.get(player);&#xA;        if (frame_for_player == null) {&#xA;            frame_for_player = 0;&#xA;            frameCount.putIfAbsent(player, frame_for_player);&#xA;        }&#xA;&#xA;        if (!WaveformFinder.getInstance().isRunning()) {&#xA;            WaveformFinder.getInstance().start();&#xA;        }&#xA;        WaveformDetail detail = WaveformFinder.getInstance().getLatestDetailFor(player);&#xA;&#xA;        if (detail != null) {&#xA;            WaveformDetailComponent component = (WaveformDetailComponent) detail.createViewComponent(&#xA;                    MetadataFinder.getInstance().getLatestMetadataFor(player),&#xA;                    BeatGridFinder.getInstance().getLatestBeatGridFor(player)&#xA;            );&#xA;            component.setMonitoredPlayer(player);&#xA;            component.setPlaybackState(player, TimeFinder.getInstance().getTimeFor(player), true);&#xA;            component.setAutoScroll(true);&#xA;            int width = 1200;&#xA;            int height = 200;&#xA;            Dimension dimension = new Dimension(width, height);&#xA;            component.setPreferredSize(dimension);&#xA;            component.setSize(dimension);&#xA;            component.setScale(1);&#xA;            component.doLayout();&#xA;&#xA;            // Create a fresh BufferedImage and clear it before rendering&#xA;            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);&#xA;            Graphics2D g = image.createGraphics();&#xA;            g.clearRect(0, 0, width, height);  // Clear any old content&#xA;&#xA;            // Draw waveform into the BufferedImage&#xA;            component.paint(g);&#xA;            g.dispose();&#xA;&#xA;            int port = 5004 &#x2B; player;&#xA;            String inputFile = port &#x2B; "_" &#x2B; frame_for_player &#x2B; ".mp4";&#xA;            // Initialize the FFmpegFrameRecorder for YUV420P&#xA;            FFmpegFrameRecorder recorder_file = new FFmpegFrameRecorder(inputFile, width, height);&#xA;            FFmpegLogCallback.set();  // Enable FFmpeg logging for debugging&#xA;            recorder_file.setFormat("mp4");&#xA;            recorder_file.setVideoCodec(avcodec.AV_CODEC_ID_H264);&#xA;            recorder_file.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);  // Use YUV420P format directly&#xA;            recorder_file.setFrameRate(FPS);&#xA;&#xA;            // Set video options&#xA;            recorder_file.setVideoOption("preset", "ultrafast");&#xA;            recorder_file.setVideoOption("tune", "zerolatency");&#xA;            recorder_file.setVideoOption("x264-params", "repeat-headers=1");&#xA;            recorder_file.setGopSize(FPS);&#xA;            try {&#xA;                recorder_file.start();  // Ensure this is called before recording any frames&#xA;                System.out.println("Recorder started successfully for player: " &#x2B; player);&#xA;            } catch (org.bytedeco.javacv.FFmpegFrameRecorder.Exception e) {&#xA;                e.printStackTrace();&#xA;            }&#xA;&#xA;            // Get all pixels in one call&#xA;            int[] pixels = new int[width * height];&#xA;            image.getRGB(0, 0, width, height, pixels, 0, width);&#xA;            recorder_file.recordImage(width,height,Frame.DEPTH_UBYTE,1,3 * width, AV_PIX_FMT_RGB24, ByteBuffer.wrap(argbToByteArray(pixels, width, height)));&#xA;            recorder_file.stop();&#xA;            recorder_file.release();&#xA;            final FFmpegFrameRecorder recorder = recorders.get(player);&#xA;            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);&#xA;&#xA;&#xA;            try {&#xA;                grabber.start();&#xA;            } catch (Exception e) {&#xA;                e.printStackTrace();&#xA;            }&#xA;            if (recorder == null) {&#xA;                try {&#xA;                    String outputStream = "rtp://127.0.0.1:" &#x2B; port;&#xA;                    FFmpegFrameRecorder initial_recorder = new FFmpegFrameRecorder(outputStream, grabber.getImageWidth(), grabber.getImageHeight());&#xA;                    initial_recorder.setFormat("rtp");&#xA;                    initial_recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);&#xA;                    initial_recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);&#xA;                    initial_recorder.setFrameRate(grabber.getFrameRate());&#xA;                    initial_recorder.setGopSize(FPS);&#xA;                    initial_recorder.setVideoOption("x264-params", "keyint=60");&#xA;                    initial_recorder.setVideoOption("rtsp_transport", "tcp");&#xA;                    initial_recorder.start();&#xA;                    recorders.putIfAbsent(player, initial_recorder);&#xA;                    frameCount.putIfAbsent(player, 0);&#xA;                    putToRTP(player, grabber, initial_recorder);&#xA;                }&#xA;                catch (Exception e) {&#xA;                    e.printStackTrace();&#xA;                }&#xA;            }&#xA;            else {&#xA;                putToRTP(player, grabber, recorder);&#xA;            }&#xA;            File file = new File(inputFile);&#xA;            if (file.exists() &amp;&amp; file.delete()) {&#xA;                System.out.println("Successfully deleted file: " &#x2B; inputFile);&#xA;            } else {&#xA;                System.out.println("Failed to delete file: " &#x2B; inputFile);&#xA;            }&#xA;        }&#xA;    }&#xA;&#xA;    public static void putToRTP(int player, FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder) throws FrameGrabber.Exception {&#xA;        final Frame frame = grabber.grabFrame();&#xA;        int frameCount_local = frameCount.get(player);&#xA;        frame.keyFrame = frameCount_local&#x2B;&#x2B; % FPS == 0;&#xA;        frameCount.put(player, frameCount_local);&#xA;        try {&#xA;            recorder.record(frame);&#xA;        } catch (FFmpegFrameRecorder.Exception e) {&#xA;            throw new RuntimeException(e);&#xA;        }&#xA;    }&#xA;    public static byte[] argbToByteArray(int[] argb, int width, int height) {&#xA;        int totalPixels = width * height;&#xA;        byte[] byteArray = new byte[totalPixels * 3];  // 4 bytes per pixel (ARGB)&#xA;&#xA;        for (int i = 0; i &lt; totalPixels; i&#x2B;&#x2B;) {&#xA;            int argbPixel = argb[i];&#xA;&#xA;            byteArray[i * 3] = (byte) ((argbPixel >> 16) &amp; 0xFF);  // Red&#xA;            byteArray[i * 3 &#x2B; 1] = (byte) ((argbPixel >> 8) &amp; 0xFF);   // Green&#xA;            byteArray[i * 3 &#x2B; 2] = (byte) (argbPixel &amp; 0xFF);  // Blue&#xA;        }&#xA;&#xA;        return byteArray;&#xA;    }&#xA;&#xA;&#xA;    public static void main(String[] args) throws Exception {&#xA;        VirtualCdj.getInstance().setDeviceNumber((byte) 4);&#xA;        CrateDigger.getInstance().addDatabaseListener(new DBService());&#xA;        props.put("bootstrap.servers", "localhost:9092");&#xA;        props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");&#xA;        props.put("value.serializer", "com.bugbytz.prolink.CustomSerializer");&#xA;        props.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG, "20971520");&#xA;&#xA;        VirtualCdj.getInstance().addUpdateListener(update -> {&#xA;            if (update instanceof CdjStatus) {&#xA;                try (Producer producer = new KafkaProducer&lt;>(props)) {&#xA;                    DecimalFormat df_obj = new DecimalFormat("#.##");&#xA;                    DeviceStatus deviceStatus = new DeviceStatus(&#xA;                            update.getDeviceNumber(),&#xA;                            ((CdjStatus) update).isPlaying() || !((CdjStatus) update).isPaused(),&#xA;                            ((CdjStatus) update).getBeatNumber(),&#xA;                            update.getBeatWithinBar(),&#xA;                            Double.parseDouble(df_obj.format(update.getEffectiveTempo())),&#xA;                            Double.parseDouble(df_obj.format(Util.pitchToPercentage(update.getPitch()))),&#xA;                            update.getAddress().getHostAddress(),&#xA;                            byteArrayToMacString(DeviceFinder.getInstance().getLatestAnnouncementFrom(update.getDeviceNumber()).getHardwareAddress()),&#xA;                            ((CdjStatus) update).getRekordboxId(),&#xA;                            update.getDeviceName()&#xA;                    );&#xA;                    ProducerRecord record = new ProducerRecord&lt;>("device-status", "device-" &#x2B; update.getDeviceNumber(), deviceStatus);&#xA;                    try {&#xA;                        producer.send(record).get();&#xA;                    } catch (InterruptedException ex) {&#xA;                        throw new RuntimeException(ex);&#xA;                    } catch (ExecutionException ex) {&#xA;                        throw new RuntimeException(ex);&#xA;                    }&#xA;                    producer.flush();&#xA;                    if (!WaveformFinder.getInstance().isRunning()) {&#xA;                        try {&#xA;                            WaveformFinder.getInstance().start();&#xA;                        } catch (Exception ex) {&#xA;                            throw new RuntimeException(ex);&#xA;                        }&#xA;                    }&#xA;                }&#xA;            }&#xA;        });&#xA;        DeviceFinder.getInstance().addDeviceAnnouncementListener(new DeviceAnnouncementAdapter() {&#xA;            @Override&#xA;            public void deviceFound(DeviceAnnouncement announcement) {&#xA;                if (!streamingPlayers.contains(announcement.getDeviceNumber())) {&#xA;                    streamingPlayers.add(announcement.getDeviceNumber());&#xA;                    schedules.putIfAbsent(announcement.getDeviceNumber(), scheduler.scheduleAtFixedRate(() -> {&#xA;                        try {&#xA;                            Runnable task = () -> {&#xA;                                try {&#xA;                                    updateWaveformForPlayer(announcement.getDeviceNumber());&#xA;                                } catch (InterruptedException e) {&#xA;                                    System.out.println("Thread interrupted");&#xA;                                } catch (Exception e) {&#xA;                                    throw new RuntimeException(e);&#xA;                                }&#xA;                                System.out.println("Lambda thread work completed!");&#xA;                            };&#xA;                            task.run();&#xA;                        } catch (Exception e) {&#xA;                            e.printStackTrace();&#xA;                        }&#xA;                    }, 0, FRAME_INTERVAL_MS, TimeUnit.MILLISECONDS));&#xA;                }&#xA;            }&#xA;&#xA;            @Override&#xA;            public void deviceLost(DeviceAnnouncement announcement) {&#xA;                if (streamingPlayers.contains(announcement.getDeviceNumber())) {&#xA;                    schedules.get(announcement.getDeviceNumber()).cancel(true);&#xA;                    streamingPlayers.remove(announcement.getDeviceNumber());&#xA;                }&#xA;            }&#xA;        });&#xA;        BeatGridFinder.getInstance().start();&#xA;        MetadataFinder.getInstance().start();&#xA;        VirtualCdj.getInstance().start();&#xA;        TimeFinder.getInstance().start();&#xA;        DeviceFinder.getInstance().start();&#xA;        CrateDigger.getInstance().start();&#xA;&#xA;        try {&#xA;            LoadCommandConsumer consumer = new LoadCommandConsumer("localhost:9092", "load-command-group");&#xA;            Thread consumerThread = new Thread(consumer::startConsuming);&#xA;            consumerThread.start();&#xA;&#xA;            Runtime.getRuntime().addShutdownHook(new Thread(() -> {&#xA;                consumer.shutdown();&#xA;                try {&#xA;                    consumerThread.join();&#xA;                } catch (InterruptedException e) {&#xA;                    Thread.currentThread().interrupt();&#xA;                }&#xA;            }));&#xA;            Thread.sleep(60000);&#xA;        } catch (InterruptedException e) {&#xA;            System.out.println("Interrupted, exiting.");&#xA;        }&#xA;    }&#xA;}&#xA;</integer></track>

    &#xA;