Registratore dello schermo

Mi interessa una libreria (per Windows) scritta in Delphi / Pascal o C ++ che mi permetta di registrare (in un formato video) lo schermo del desktop, requisiti:

  • deve essere in grado di specificare il frame rate, o almeno essere in grado di registrare @ 5fps;
  • deve essere open source o gratuito;
  • il formato di output potrebbe essere quasi qualsiasi, ma la qualità deve essere sufficiente per essere in grado di leggere il testo dalla registrazione;

vantaggi, se ansible:

  • opzione per registrare senza colors (scala di grigi);
  • più display consapevoli ;
  • multipiattaforma (Windows e Linux, anche altre piattaforms sarebbero belle, ma non necessarie);

Se per caso, non ho spiegato qualcosa di giusto, non esitate a chiedere in modo che possa riformulare o fornire maggiori dettagli, ecc.

FFMPEG supporta la cattura dello schermo (fusione) ed è multipiattaforma.

Potresti provare Windows Media Encoder (freeware, solo wmv / asf) o VLC (GPL, Win / OSX / Linux). Si noti che le visualizzazioni “accelerate hardware” (ad esempio, rendering Direct3D e OpenGL) non saranno disponibili e si verificherà una perdita di qualità a causa della compressione video. Quanto perdi dipenderà dalle tue impostazioni (codec, bitrate, risoluzione, ecc.)

Esempio: come eseguire lo streaming del desktop tramite 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}' 

Puoi trovare più opzioni nella documentazione VLC , per esempio per salvare il tuo stream come un file.

Questo è quello che uso con Delphi, si chiama ” Professional Screen Camera Component “. Devo ammettere che devo apportare alcune modifiche per supportare le versioni unicode (sostituire PChar con PAnsiChar, sostituire Char con AnsiChar).

Registra felicemente il framerate su cui l’ho impostato, codificherà il video con qualsiasi codec che specifichi (se lo desidero) e ti permetterà di specificare la regione che desideri registrare.

Viene fornito anche con un progetto demo!

Oh, ed è gratuito / open source!

FFmpeg può essere utilizzato per catturare lo schermo.

guarda la demo video registrata sullo schermo usando FFMPEG: https://www.youtube.com/watch?v=a31bBY3HuxE

Formato contenitore: MP4

Codec: MPEG4

Segui i passaggi per registrare lo schermo in video usando FFmpeg e altre librerie.

  1. Inizializza i registri richiesti

  2. usa x11grab (per il sistema operativo Linux) in av_find_input_format

  3. menziona la posizione per catturare il video sullo schermo (ad esempio “: 0.0 + 10.250” in av_format_open_input)

  4. Ora vai per l’inizializzazione dei parametri video regolari e l’allocazione della memoria.

  5. iniziare a catturare i fotogrammi e memorizzarli in un file.

  6. Infine, rilascia le risorse assegnate una volta completate!

sotto il codice è scritto in c ++ e usa il formato video della piattaforma Linux (ubuntu) in formato mp4.

 // sample code to record the computer screen ! #ifndef SCREENRECORDER_H #define SCREENRECORDER_H #include  #include  #include  #include  #include  #include  #include  #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<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 */ 

Ecco lo screenshot. Ecco lo screenshot

codice di lavoro completo nel link github :

Non l’ho mai fatto prima, ma quando ho cercato su Google (come sono sicuro che tu abbia), mi sono imbattuto in questo:

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

Sembra che dovrebbe fare ciò che stai chiedendo abbastanza facilmente (per Windows), e non ha alcuna licenza associata (come confermato in fondo). Non credo che sia configurato come una libreria, ma sono sicuro che si potrebbe colbind l’interfaccia alle funzioni WinCap di esempio in una con facilità ragionevole.

Probabilmente è eccessivo per le tue esigenze, ma il componente video grabber di DataStead può anche registrare l’attività dello schermo e salvare l’output come file video. Vedi http://www.datastead.com/products/tvideograbber/overview.html . Non sono associato a DataStead, ma sono stato un cliente per alcuni anni e funziona benissimo.