Bildschirm recorder [closed]

Lesezeit: 13 Minuten

Ich interessiere mich für eine in Delphi/Pascal oder C++ geschriebene Bibliothek (für Windows), mit der ich den Desktop-Bildschirm (in einem Videoformat) aufzeichnen kann. Anforderungen:

  • muss in der Lage sein, die Bildrate festzulegen oder zumindest @ 5 fps aufnehmen zu können;
  • muss Open Source oder kostenlos sein;
  • das Ausgabeformat kann fast beliebig sein, aber die Qualität muss gut genug sein, um Text aus der Aufzeichnung lesen zu können;

Pluspunkte, wenn möglich:

  • Option zum Aufnehmen ohne Farben (Graustufen);
  • Mehrfachanzeige bewusst;
  • plattformübergreifend (Windows & Linux, andere Plattformen wären auch schön, aber nicht notwendig);

Wenn ich aus irgendeinem Grund etwas nicht richtig erklärt habe, können Sie gerne nachfragen, damit ich es anders formulieren oder mehr Details usw. geben kann.

  • “ohne Farben” bedarf der Klärung. Meinst du vielleicht einfarbig? Idealerweise möchten Sie die Farbpalette reduzieren können, um Platz zu sparen. dh auf 256 Farben reduzieren.

    – Chris Thornton

    29. November 2011 um 20:50 Uhr

  • Auf was aufnehmen? Eine Reihe von .bmp-Frames? .mpg? Blinken? H264? Maus/Tastatur mit aufnehmen?

    – Chris Thornton

    29. November 2011 um 20:51 Uhr

  • @Chris Ich habe die Frage bearbeitet, aber kurz gesagt, jede Ausgabeform, solange die Qualität gut genug ist, um Text aus der Aufnahme zu lesen.

    Benutzer497849

    29. November 2011 um 21:00 Uhr

FFMPEG unterstützt Bildschirmaufnahme (Casting) und ist plattformübergreifend.

  • +1 Dies ist ein guter Vorschlag. Sie können sogar finden Delphi-Header für ffmpeg dort draußen.

    – ym

    30. November 2011 um 0:21 Uhr

  • @yms, absolut, und ich benutze sie. Aber ich empfehle die mit Delphi FFMPEG-Headern gekennzeichneten nicht, da sie veraltet und unvollständig sind. Suchen Sie stattdessen nach einem Open-Source-Delphi-Projekt, das FFMPEG verwendet (es gibt viele) und testen Sie deren Header auf Größe.

    – Marcus Adams

    30. November 2011 um 0:51 Uhr


  • Nach einem engen Kampf zwischen VLC und FFMPEG muss ich mich für FFMPEG entscheiden, ich habe das Gefühl, dass es besser zu meinen Bedürfnissen passt, danke @Marcus.

    Benutzer497849

    3. Dezember 2011 um 19:48 Uhr

  • Können Sie mir auf ein C++-Tool für Win32 (Windows) verweisen, das FFMPEG verwendet?

    – Michael Häphrati

    15. August 2019 um 10:46 Uhr

Du könntest es versuchen Windows Media-Encoder (Freeware, nur wmv/asf) oder VLC (GPL, Win/OSX/Linux). Beachten Sie, dass “hardwarebeschleunigte” Ansichten (z. B. Direct3D- und OpenGL-Rendering) nicht verfügbar sind und aufgrund der Videokomprimierung ein gewisser Qualitätsverlust auftritt. Wie viel Sie verlieren, hängt von Ihren Einstellungen ab (Codec, Bitrate, Auflösung usw.)

Beispiel: So streamen Sie Ihren Desktop mit VLC

vlc screen:// :screen-fps=30 :screen-caching=100 --sout '#transcode{vcodec=mp4v,vb=4096,acodec=mpga,ab=256,scale=1,width=1280,height=800}:rtp{dst=192.168.1.2,port=1234,access=udp,mux=ts}'

Weitere Optionen finden Sie in VLC-Dokumentationum beispielsweise Ihren Stream als Datei zu speichern.

  • Nein, es ist eine schreckliche Option, verschwenden Sie nicht Ihre Zeit.

    – Joda

    8. April 2019 um 18:29 Uhr

Dies ist die, die ich mit Delphi verwende, sie heißt “Professionelle Bildschirmkamerakomponente“. Zugegebenermaßen musste ich einige Änderungen vornehmen, um Unicode-Versionen zu unterstützen (PChar durch PAnsiChar ersetzen, Char durch AnsiChar ersetzen).

Es nimmt problemlos mit der von mir eingestellten Framerate auf, codiert das Video mit dem von mir festgelegten Codec (wenn ich möchte) und ermöglicht es Ihnen, die Region anzugeben, die Sie aufnehmen möchten.

Kommt auch mit einem Demo-Projekt!

Oh, und es ist kostenlos/Open Source!

  • danke, das ist auch eine gute Option, ich bin zwischen VCL, FFMPEG und diesem.

    Benutzer497849

    30. November 2011 um 0:38 Uhr

  • Ich habe tatsächlich die auf dieser Komponente aufgebaute Demo verwendet, um mein Lua4Delphi-Demovideo aufzunehmen … nur damit Sie wissen, dass es tatsächlich funktioniert (und HD unterstützt).

    – LaKraven

    30. November 2011 um 0:40 Uhr

  • Ich war gerade dabei, eine STREAMING-Komponente zu entwickeln, um daneben zu sitzen … da dies (gekoppelt mit einem Tastatur- / Maus-Erfassungs- und Emulationssystem) auch eine gute Grundlage für eine Remote-Desktop-Server / Client-Architektur bilden würde!

    – LaKraven

    30. November 2011 um 0:41 Uhr

  • VLC kann streamen, und für Remotedesktop kann Windows RDS es ganz gut … Ich sehe keinen guten Grund, das Rad neu zu erfinden (:

    Benutzer497849

    30. November 2011 um 0:52 Uhr

  • @DorinDuminca, du kennst mich gut genug, um zu wissen, dass ich lebe, um das Rad neu zu erfinden 😉

    – LaKraven

    30. November 2011 um 1:13 Uhr

Es ist wahrscheinlich übertrieben für Ihre Bedürfnisse, aber die Video-Grabber-Komponente von DataStead kann auch Bildschirmaktivitäten aufzeichnen und die Ausgabe als Videodatei speichern. Sehen http://www.datastead.com/products/tvideograbber/overview.html. Ich bin nicht mit DataStead verbunden, bin aber seit einigen Jahren Kunde und es funktioniert großartig.

Bildschirm recorder closed
Abdullah Farweez

FFmpeg kann verwendet werden, um den Bildschirm zu erfassen.

Sehen Sie sich die bildschirmaufgezeichnete Videodemo mit FFMPEG an: https://www.youtube.com/watch?v=a31bBY3HuxE

Containerformat: MP4

Codec: MPEG4

Befolgen Sie die Schritte, um den Bildschirm mithilfe von FFmpeg und anderen Bibliotheken als Video aufzuzeichnen.

  1. Erforderliche Register initialisieren

  2. Verwenden Sie x11grab (für Linux OS) im av_find_input_format

  3. Erwähnen Sie die Position, um das Video auf dem Bildschirm aufzunehmen (z. B. „:0.0+10.250“ in av_format_open_input).

  4. Gehen Sie jetzt zur regulären Initialisierung der Videoparameter und zur Speicherzuweisung.

  5. Starten Sie die Aufnahme der Frames und speichern Sie sie in einer Datei.

  6. Geben Sie schließlich die zugewiesenen Ressourcen frei, sobald Sie fertig sind!.

Der folgende Code ist in C++ geschrieben und verwendet die Linux-Plattform (Ubuntu). Das Videoformat liegt im mp4-Format vor.

// sample code to record the computer screen !

      #ifndef SCREENRECORDER_H
      #define SCREENRECORDER_H

      #include <iostream>
      #include <cstdio>
      #include <cstdlib>
      #include <fstream>
      #include <cstring>
      #include <math.h>
      #include <string.h>

      #define __STDC_CONSTANT_MACROS

      //FFMPEG LIBRARIES
      extern "C"
      {
      #include "libavcodec/avcodec.h"
      #include "libavcodec/avfft.h"

      #include "libavdevice/avdevice.h"

      #include "libavfilter/avfilter.h"
      #include "libavfilter/avfiltergraph.h"
      #include "libavfilter/buffersink.h"
      #include "libavfilter/buffersrc.h"

      #include "libavformat/avformat.h"
      #include "libavformat/avio.h"

      // libav resample

      #include "libavutil/opt.h"
      #include "libavutil/common.h"
      #include "libavutil/channel_layout.h"
      #include "libavutil/imgutils.h"
      #include "libavutil/mathematics.h"
      #include "libavutil/samplefmt.h"
      #include "libavutil/time.h"
      #include "libavutil/opt.h"
      #include "libavutil/pixdesc.h"
      #include "libavutil/file.h"

      // lib swresample

      #include "libswscale/swscale.h"

      }



      class ScreenRecorder
      {
      private:
        AVInputFormat *pAVInputFormat;
        AVOutputFormat *output_format;

        AVCodecContext *pAVCodecContext;

        AVFormatContext *pAVFormatContext;

        AVFrame *pAVFrame;
        AVFrame *outFrame;

        AVCodec *pAVCodec;
        AVCodec *outAVCodec;

        AVPacket *pAVPacket;

        AVDictionary *options;

        AVOutputFormat *outAVOutputFormat;
        AVFormatContext *outAVFormatContext;
        AVCodecContext *outAVCodecContext;

        AVStream *video_st;
        AVFrame *outAVFrame;

        const char *dev_name;
        const char *output_file;

        double video_pts;

        int out_size;
        int codec_id;
        int value;
        int VideoStreamIndx;

      public:

        ScreenRecorder();
        ~ScreenRecorder();

        int openCamera();
        int init_outputfile();
        int collectFrames();

      };

      #endif


      using namespace std;

      ScreenRecorder::ScreenRecorder()
      {
        cout<<"\n\n Registering required functions...";
        av_register_all();
        avcodec_register_all();
        avdevice_register_all();
        cout<<"\n\n Registered successfully...";
      }

      ScreenRecorder::~ScreenRecorder()
      {

        avformat_close_input(&pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n1.Success : avformat_close_input()";
        }
        else
        {
        cout<<"\n\nError : avformat_close_input()";
        }

        avformat_free_context(pAVFormatContext);
        if( !pAVFormatContext )
        {
        cout<<"\n\n2.Success : avformat_free_context()";
        }
        else
        {
        cout<<"\n\nError : avformat_free_context()";
        }

      cout<<"\n\n---------------Successfully released all resources------------------\n\n\n";
      cout<<endl;
      cout<<endl;
      cout<<endl;
      }

      int ScreenRecorder::collectFrames()
      {
        int flag;
        int frameFinished;
      //when you decode a single packet, you still don't have information enough to have a frame [depending on the type of codec, some of them //you do], when you decode a GROUP of packets that represents a frame, then you have a picture! that's why frameFinished will let //you know you decoded enough to have a frame.

        int frame_index = 0;
        value = 0;

        pAVPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
        av_init_packet(pAVPacket);

        pAVFrame = av_frame_alloc();
        if( !pAVFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        outFrame = av_frame_alloc();//Allocate an AVFrame and set its fields to default values.
        if( !outFrame )
        {
         cout<<"\n\nError : av_frame_alloc()";
         return -1;
        }

        int video_outbuf_size;
        int nbytes = av_image_get_buffer_size(outAVCodecContext->pix_fmt,outAVCodecContext->width,outAVCodecContext->height,32);
        uint8_t *video_outbuf = (uint8_t*)av_malloc(nbytes);
        if( video_outbuf == NULL )
        {
        cout<<"\n\nError : av_malloc()";
        }

        // Setup the data pointers and linesizes based on the specified image parameters and the provided array.
        value = av_image_fill_arrays( outFrame->data, outFrame->linesize, video_outbuf , AV_PIX_FMT_YUV420P, outAVCodecContext->width,outAVCodecContext->height,1 ); // returns : the size in bytes required for src
        if(value < 0)
        {
        cout<<"\n\nError : av_image_fill_arrays()";
        }

        SwsContext* swsCtx_ ;

        // Allocate and return swsContext.
        // a pointer to an allocated context, or NULL in case of error
        // Deprecated : Use sws_getCachedContext() instead.
        swsCtx_ = sws_getContext(pAVCodecContext->width,
                            pAVCodecContext->height,
                            pAVCodecContext->pix_fmt,
                            outAVCodecContext->width,
                    outAVCodecContext->height,
                            outAVCodecContext->pix_fmt,
                            SWS_BICUBIC, NULL, NULL, NULL);


      int ii = 0;
      int no_frames = 100;
      cout<<"\n\nEnter No. of Frames to capture : ";
      cin>>no_frames;

        AVPacket outPacket;
        int j = 0;

        int got_picture;

        while( av_read_frame( pAVFormatContext , pAVPacket ) >= 0 )
        {
        if( ii++ == no_frames )break;
            if(pAVPacket->stream_index == VideoStreamIndx)
            {
                value = avcodec_decode_video2( pAVCodecContext , pAVFrame , &frameFinished , pAVPacket );
                if( value < 0)
                {
                    cout<<"Error : avcodec_decode_video2()";
                }

                if(frameFinished)// Frame successfully decoded :)
                {
                    sws_scale(swsCtx_, pAVFrame->data, pAVFrame->linesize,0, pAVCodecContext->height, outFrame->data,outFrame->linesize);
                    av_init_packet(&outPacket);
                    outPacket.data = NULL;    // packet data will be allocated by the encoder
                    outPacket.size = 0;

                    avcodec_encode_video2(outAVCodecContext , &outPacket ,outFrame , &got_picture);

                    if(got_picture)
                    {
                        if(outPacket.pts != AV_NOPTS_VALUE)
                            outPacket.pts = av_rescale_q(outPacket.pts, video_st->codec->time_base, video_st->time_base);
                        if(outPacket.dts != AV_NOPTS_VALUE)
                            outPacket.dts = av_rescale_q(outPacket.dts, video_st->codec->time_base, video_st->time_base);

                        printf("Write frame %3d (size= %2d)\n", j++, outPacket.size/1000);
                        if(av_write_frame(outAVFormatContext , &outPacket) != 0)
                        {
                            cout<<"\n\nError : av_write_frame()";
                        }

                    av_packet_unref(&outPacket);
                    } // got_picture

                av_packet_unref(&outPacket);
                } // frameFinished

            }
        }// End of while-loop

        value = av_write_trailer(outAVFormatContext);
        if( value < 0)
        {
            cout<<"\n\nError : av_write_trailer()";
        }


      //THIS WAS ADDED LATER
      av_free(video_outbuf);

      }

      int ScreenRecorder::openCamera()
      {

        value = 0;
        options = NULL;
        pAVFormatContext = NULL;

        pAVFormatContext = avformat_alloc_context();//Allocate an AVFormatContext.

        pAVInputFormat = av_find_input_format("x11grab");
        value = avformat_open_input(&pAVFormatContext, ":0.0+10,250", pAVInputFormat, NULL);
        if(value != 0)
        {
           cout<<"\n\nError : avformat_open_input\n\nstopped...";
           return -1;
        }

        value = av_dict_set( &options,"framerate","30",0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(framerate , 30 , 0)";
          return -1;
        }

        value = av_dict_set( &options, "preset", "medium", 0 );
        if(value < 0)
        {
          cout<<"\n\nError : av_dict_set(preset , medium)";
              return -1;
        }

      //    value = avformat_find_stream_info(pAVFormatContext,NULL);
        if(value < 0)
        {
          cout<<"\n\nError : avformat_find_stream_info\nstopped...";
          return -1;
        }

        VideoStreamIndx = -1;

        for(int i = 0; i < pAVFormatContext->nb_streams; i++ ) // find video stream posistion/index.
        {
          if( pAVFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO )
          {
             VideoStreamIndx = i;
             break;
          }

        } // End for-loop

        if( VideoStreamIndx == -1)
        {
          cout<<"\n\nError : VideoStreamIndx = -1";
          return -1;
        }

        // assign pAVFormatContext to VideoStreamIndx
        pAVCodecContext = pAVFormatContext->streams[VideoStreamIndx]->codec;

        pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
        if( pAVCodec == NULL )
        {
          cout<<"\n\nError : avcodec_find_decoder()";
          return -1;
        }

        value = avcodec_open2(pAVCodecContext , pAVCodec , NULL);//Initialize the AVCodecContext to use the given AVCodec.
        if( value < 0 )
        {
          cout<<"\n\nError : avcodec_open2()";
          return -1;
        }
      }

      int ScreenRecorder::init_outputfile()
      {
        outAVFormatContext = NULL;
        value = 0;
        output_file = "output.mp4";

        avformat_alloc_output_context2(&outAVFormatContext, NULL, NULL, output_file);
        if (!outAVFormatContext)
        {
            cout<<"\n\nError : avformat_alloc_output_context2()";
          return -1;
        }

      /*Returns the output format in the list of registered output formats which best matches the provided parameters, or returns NULL if there is no match.
      */
        output_format = av_guess_format(NULL, output_file ,NULL);
        if( !output_format )
        {
         cout<<"\n\nError : av_guess_format()";
         return -1;
        }

        video_st = avformat_new_stream(outAVFormatContext ,NULL);
        if( !video_st )
        {
            cout<<"\n\nError : avformat_new_stream()";
          return -1;
        }

        outAVCodecContext = avcodec_alloc_context3(outAVCodec);
        if( !outAVCodecContext )
        {
          cout<<"\n\nError : avcodec_alloc_context3()";
          return -1;
        }

        outAVCodecContext = video_st->codec;
        outAVCodecContext->codec_id = AV_CODEC_ID_MPEG4;// AV_CODEC_ID_MPEG4; // AV_CODEC_ID_H264 // AV_CODEC_ID_MPEG1VIDEO
        outAVCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
        outAVCodecContext->pix_fmt  = AV_PIX_FMT_YUV420P;
        outAVCodecContext->bit_rate = 400000; // 2500000
        outAVCodecContext->width = 1920;
        outAVCodecContext->height = 1080;
        outAVCodecContext->gop_size = 3;
        outAVCodecContext->max_b_frames = 2;
        outAVCodecContext->time_base.num = 1;
        outAVCodecContext->time_base.den = 30; // 15fps

        if (codec_id == AV_CODEC_ID_H264)
        {
         av_opt_set(outAVCodecContext->priv_data, "preset", "slow", 0);
        }

        outAVCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);
        if( !outAVCodec )
        {
         cout<<"\n\nError : avcodec_find_encoder()";
         return -1;
        }

      // Some container formats (like MP4) require global headers to be present
      // Mark the encoder so that it behaves accordingly.

        if ( outAVFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
        {
            outAVCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
        }

        value = avcodec_open2(outAVCodecContext, outAVCodec, NULL);
        if( value < 0)
        {
            cout<<"\n\nError : avcodec_open2()";
            return -1;
        }

        if ( !(outAVFormatContext->flags & AVFMT_NOFILE) )
        {
         if( avio_open2(&outAVFormatContext->pb , output_file , AVIO_FLAG_WRITE ,NULL, NULL) < 0 )
         {
          cout<<"\n\nError : avio_open2()";
         }
        }



        if(!outAVFormatContext->nb_streams)
        {
            cout<<"\n\nError : Output file dose not contain any stream";
          return -1;
        }

        value = avformat_write_header(outAVFormatContext , &options);
        if(value < 0)
        {
            cout<<"\n\nError : avformat_write_header()";
            return -1;
        }

        cout<<"\n\nOutput file information :\n\n";
        av_dump_format(outAVFormatContext , 0 ,output_file ,1);
      }

      int main()
      {
        ScreenRecorder s_record;

        s_record.openCamera();
        s_record.init_outputfile();
        s_record.collectFrames();

        cout<<"\n\n---------EXIT_SUCCESS------------\n\n";

      return 0;
      }


      /* to compile the code : g++ -Wno-format-zero-length -Wno-write-strings -L/home/abdullah/ffmpeg_build/lib/ -L/usr/lib/x86_64-linux-gnu/ -I/home/abdullah/ffmpeg_build/include/ -o ScreenRecorder ScreenRecorder.cpp -lavdevice -lavfilter -lswscale -lavformat -lavcodec -lavutil -lswresample -lm -lva -lpthread -lvorbis -lvpx -lopus -lz -lpostproc -ldl -lfdk-aac -lmp3lame -lvorbisenc -lvorbisfile -lx264 -ltheora -lx265 -ltheoraenc -ltheoradec -ldl -lrt -lbz2 -lasound -lSDL -lSDLmain -lSDL_ttf -lfreetype -lass -llzma -lftgl -lperl -lcrypto -lxcb -lxcb-shm -lxcb-xfixes -lao -lxcb-shape -lfftw3 */

Hier ist der Screenshot.
Hier ist der Screenshot

Vollständiger Arbeitscode im Github-Link:

  • Irgendwas für Windows?

    – Michael Häphrati

    15. August 2019 um 10:41 Uhr

  • @MichaelHaephrati, Verwenden Sie GDIgrab für Windows (32 Bit) und stellen Sie sicher, dass die Eingabe-URL „Desktop“ im av_input_format ist.

    – Abdullah Farweez

    21. August 2019 um 11:55 Uhr

1646317814 621 Bildschirm recorder closed
John Humphreys

Ich habe das noch nie selbst gemacht, aber als ich herumgegoogelt habe (was Sie sicher getan haben), bin ich auf Folgendes gestoßen:

http://www.codeproject.com/KB/GDI/barry_s_screen_capture.aspx

Es sieht so aus, als ob es das tun sollte, was Sie verlangen, relativ einfach (für Windows), und es ist keine Lizenz damit verbunden (wie unten bestätigt). Ich glaube nicht, dass es als Bibliothek eingerichtet ist, aber ich bin sicher, dass Sie die Schnittstelle mit den Beispiel-WinCap-Funktionen mit angemessener Leichtigkeit in eine binden könnten.

  • Irgendwas für Windows?

    – Michael Häphrati

    15. August 2019 um 10:41 Uhr

  • @MichaelHaephrati, Verwenden Sie GDIgrab für Windows (32 Bit) und stellen Sie sicher, dass die Eingabe-URL „Desktop“ im av_input_format ist.

    – Abdullah Farweez

    21. August 2019 um 11:55 Uhr

1646317814 655 Bildschirm recorder closed
Anil8753

Verwenden Sie Bildschirmaufnahme Lite
https://github.com/smasherprog/screen_capture_lite

Dies ist eine C++-Bibliothek und plattformübergreifend

  • Ich frage mich, wie ich mit dieser Bibliothek im Videoformat speichern kann. Ich führe die Beispiele aus und erhalte die Screenshots. Aber mein Ziel ist es, diese Daten als Videodateien zu erfassen, ohne sie als Bilder zu speichern. Könntest du mir bitte einen Weg zeigen?

    – Thunfisch

    12. Oktober 2020 um 8:35 Uhr

924340cookie-checkBildschirm recorder [closed]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy