xsharp.eu • Issues trying to get a thumbnail extracted from a MP4 video
Page 1 of 1

Issues trying to get a thumbnail extracted from a MP4 video

Posted: Thu Nov 13, 2025 6:47 pm
by ic2
I am trying to extract a thumbnail from a MP4 file. I wonder if anybody has tried this and could tell me what's wrong.

As there's no built in method in Windows, like there is for pictures, I started with AI generated C# code. Not X# code unfortunately as AI won't supply that. But hopefully someone has an idea of what causes the issue; StackOverflow seems more logical but I rarely had any results there in the past.

The original code assigns a control as follows:

Code: Select all

private static Bitmap ExtractThumbnailTryFromAI(string filePath, TimeSpan position)
{
Bitmap bitmap = null;
//var thread = new Thread(() =>
//{
var wmp =   new AxWMPLib.AxWindowsMediaPlayer();
var form = new Form();
form.Controls.Add(wmp);
wmp.CreateControl();
wmp.URL= filePath;
wmp.settings.autoStart = false;
wmp.Ctlcontrols.currentPosition = position.TotalSeconds;
wmp.Ctlcontrols.play();
wmp.Ctlcontrols.pause();
bitmap = new Bitmap(wmp.Width, wmp.Height);	// Capture the video frame from the control
wmp.DrawToBitmap(bitmap, new Rectangle(0, 0, wmp.Width, wmp.Height));
form.Dispose();
}

Issue 1
Here the problem is I get Exception of type 'System.Windows.Forms.AxHost+InvalidActiveXStateException' was thrown, directly after the wmp.URL= filePath; Even after a (long) waiting time.

I have no idea how to get the required ActiveState (=Playing) by code. Remarkable detail is that I get the same exception from the ImmediateWindow UNLESS I first type wmp or ?wmp, showing 100 properties of the control. After that the program can continue without the exception. How can I do programmatically what this IW command achieves?

It doesn't make a difference to run it from a new Thread.

I have also tried to insert this code:

Code: Select all

int wait = 0; // Wait for the media to be ready and frame to be rendered
while (wmp.playState != WMPLib.WMPPlayState.wmppsPlaying && wait < 5000)
{
    Thread.Sleep(100);
    wait += 100;
}

But the state of the control remains wmppsTransitioning , also after this 5 seconds.

Issue 2

After having issue 1, I decided to capture from the WindowsMedia Player control on a Winforms form after I press a Start button. The video starts playing and I found out that the video isn't played before the whole method behind the button ends. So I added a new button calling both 12 year old code and the modern code I got from AI. The result is that the old code saves a picture, not completely as I want it as the controls of the MediaPlayer are included. Still the 'new' code keeps saving a black screen. See below for the code.

When I run the 2 Capture methods after starting the video, I get the a black screen in both (=issue 1)

Obviously I want the capture to run without the need for a user to click a button after starting a video and also I would prefer to use the 2nd method without ending up with a black screen. Any help is appreciated.

Dick

Code: Select all

private void CaptureNowNewMethod()
{
Bitmap bitmap = null;
var tPos=TimeSpan.FromSeconds(1);
axWindowsMediaPlayer1.Ctlcontrols.currentPosition = tPos.TotalSeconds;
axWindowsMediaPlayer1.Ctlcontrols.pause();
bitmap = new Bitmap(axWindowsMediaPlayer1.Width,axWindowsMediaPlayer1.Height);  // Capture the video frame
axWindowsMediaPlayer1.DrawToBitmap(bitmap,new Rectangle(0,0,axWindowsMediaPlayer1.Width,axWindowsMediaPlayer1.Height));
if(bitmap != null)
{
string outputFile = Path.Combine("c:\\temp\\","PicFromNewMethod.bmp");
bitmap.Save(outputFile,ImageFormat.Bmp);
}}


private void CaptureNowOldMethod()
{
if(!string.IsNullOrEmpty(axWindowsMediaPlayer1.URL))
 {
  var tPos=TimeSpan.FromSeconds(1);
  axWindowsMediaPlayer1.Ctlcontrols.currentPosition = tPos.TotalSeconds;
  axWindowsMediaPlayer1.Ctlcontrols.pause();
  System.Drawing.Image ret = null;
  try
    {  
     Bitmap bitmap = new Bitmap(axWindowsMediaPlayer1.Width,axWindowsMediaPlayer1.Height);
	{
	   Graphics g = Graphics.FromImage(bitmap);
		{
		  Graphics gg = axWindowsMediaPlayer1.CreateGraphics();
			{
                          this.BringToFront();
				g.CopyFromScreen(
				axWindowsMediaPlayer1.PointToScreen(
				new System.Drawing.Point()).X,
				axWindowsMediaPlayer1.PointToScreen(
				new System.Drawing.Point()).Y,
				0,0,
				new System.Drawing.Size(
				  axWindowsMediaPlayer1.Width,
					axWindowsMediaPlayer1.Height)
				);
	                     }
                           }
                           {
				using(MemoryStream ms = new MemoryStream())
				{
				  bitmap.Save(ms,System.Drawing.Imaging.ImageFormat.Bmp);
				  ret = System.Drawing.Image.FromStream(ms);
				  string outputFile = Path.Combine("c:\\temp\\","PicFromOldMethod.bmp");
			          ret.Save(outputFile);
				}}}
				}
				catch(Exception ex){}
			}}

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Fri Nov 14, 2025 12:31 am
by Chris
Hi Dick,

It's encouraging to see that AI tools can still suggest a lot of nonsense :)


From what I read, this method cannot work, because DrawToBitmap() is not supported from the media player control, that's why you get a black image.

I'm sure there must be a generally better way to achieve this, but I experimented a bit with a similar way of doing it and doing a direct screenshot. If indeed it's an ok method for you to produce the thumbnail while having the video shown playing on screen, the attached solution should give you at least a starting point. You will need to adjust the filenames in the code of course.

VideoCapture.zip
(8.81 KiB) Downloaded 48 times

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Fri Nov 14, 2025 8:50 pm
by ic2
Hello Chris,

Wow, that is fantastic. I was away the whole day but I am going to check out your code very soon.

And I totally agree with you about AI. My general feeling is: when Microsoft embraces it, it is bound to fail. Everything Microsoft has done has failed except there very mediocre OS Windows, their somewhat mediocre Office 365 and their overpriced cloudservices. And they believe in AI so that must be the beginning of the end :D

I read in a StackOverflow survey https://survey.stackoverflow.co/2025/ai that 77% of all programmers use AI for code suggestions but that only 3% says "highly trust" and the positive sentiment has even decreased from last year. Like I had with this one. I had not expected DrawToBitmap() simply couldn't work; in most AI suggested code some key element is missing, and one doesn't not expect code which is plain wrong.

Anyhow, thanks again. I'll let you know the outcome soon!

Dick

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Tue Nov 18, 2025 7:00 pm
by ic2
Hello Chris,

Your sample works indeed and it was my first X# Core program actually ;)

I've been working on some improvements. First it seems that the scaling factor does not make a differences. I retrieved it from Windows using the following code but after I set my scailng to 125% (and saw my screen contents enlarge) the calculation still yielded 1 and the captured picture did not change:

Code: Select all

nDeviceDPI:=THIS.DeviceDpi																				// This does not seem to be different with a scaling of <>100%, it is always 1
rScreenScaling:=nDeviceDPI/96																					// If the scaling is higher, it does not seeem to create a differently sized picure
Then you do not need to compensate for borders and you can set the start position like this:

Code: Select all

wmp.uiMode:="none"		// Do not show borders or controls so we get the video content only
wmp.Ctlcontrols.currentPosition:=500// Set desired start position (in seconds)
wmp:Ctlcontrols:play()
Then there is one other thing I wanted to improve, instead of building a timer waiting 3 seconds to capture I added this even handler to the WMP control (using the lightning button in Properties):

Code: Select all

PRIVATE METHOD wmp_PlayStateChange(sender AS System.Object, e AS AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) AS VOID STRICT
	IF (e.newState == (INT)WMPLib.WMPPlayState.wmppsPlaying)
            CaptureNow()
       endif
return
I moved the relevant capturing code to the method CaptureNow. But unfortunately, even though the event reaches the IF statement, so I may expect the video to be playing, it captures a black screen.

Do you have any idea why?
I can still allow for some pause (if I preceed the capture with e.g. a Messagebox, it will work). But it is not more than a workaround...
Then I've got 2 remaining questions

1 The Wait command from VO to achieve this pause does not seem to work anymore. Is there an X# equivalent? [EDIT: see next message]
2 This is very annoying and I've seen this with one of our main programs too: If I click the closing cross in the window, the keeps running (and usually starts emitting errors because the window did close. I always have to go to the Task Manager, where the program is either in the App list or in the Background Processes, randomly it seems. [EDIT: see next message]

How can I prevent that from happening?

[EDIT] And maybe one more question: Every subject in the MS documentation in AxWindowsMediaPlayer says that the Windows Media Player SDK is a legacy feature. Do you think I should translate it to the MediaPlayer Class to prevent it from not working at some point in time?

Dick

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Tue Nov 18, 2025 8:40 pm
by ic2
As a follow up (for most readers on the message below), after some more experimenting:

This seems to work to capture the correct moment (and the Sleep below I know from X# looks like a good alternative for Wait):

Code: Select all

PRIVATE METHOD wmp_PlayStateChange(sender AS System.Object, e AS AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) AS VOID STRICT
// Event handler generated by selecting the MediaPlayer, select tab Properties, lightning symbol from tab, then double click on PlayStateChange
// In the Designer code this generates SELF:wmp:PlayStateChange	+=	AxWMPLib._WMPOCXEvents_PlayStateChangeEventHandler{ SELF, @wmp_PlayStateChange() }
// Called when the video is playing, then it captures the position

	IF (e.newState == (INT)WMPLib.WMPPlayState.wmppsPlaying)
			wmp.Ctlcontrols.pause()
			System.Threading.Thread.Sleep(1000)
			SELF:CaptureNow()
	ENDIF
	RETURN
END METHOD 
However there is one remarkable thing. Basically I do not need the timer you added to allow a 3 seconds of playing before capturing. I separated the capture code and call it from the event. But as soon as I remove the timer, which directly follows wmp:Ctlcontrols:play() the screen flashes briefly and disappears and nothing is played or captured. I I let the timer run for about 2 seconds (doing nothing in the loop except setting the exit condition variable to true - and less captures a black screen) everything works again. Also a Messagebox works to keep the window on the screen for a while. A System.Threading.Thread.Sleep(5000) will just show a white window and nothing is captured.

My idea is that the program must be doing some non-thread holding thing in order to allow the capture do actually capture something at all.

And this also brings me to a theory: I think in the previous test my timer kept running (it never set the logical anymore). Could that cause a program to remain running despite the main window being closed ? Then we have to look for a timer in the other program too.


Dick

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Tue Nov 18, 2025 11:22 pm
by Chris
Hi Dick,

Good idea using the PlayStateChange event, I had not looked into that!

The idea for using a timer is to run a loop that calls DoEvents() for a couple seconds, to allow the GUI to "breathe" and do any work needed to start the video (which apparently happens asynchronously), then capture it after it has started. If you use Sleep(), then you completely freeze the GUI for the given time, so it prevents the code from working.

One thing I forgot to add in the code I sent you is to add a timer:Stop() (and better also Dispose() ) after the timer has ticked, because if you do not do that, then that code will be executed again in the next timer tick.

Re: Issues trying to get a thumbnail extracted from a MP4 video

Posted: Wed Nov 19, 2025 12:50 pm
by ic2
Hello Chris,

Thanks again a lot for your example and also confirming why the program needs a timer. I found that it is only working correctly with a brief timer (1 second; I also added the Stop and Dispose) and 1 second sleep in wmp_PlayStateChange. As I pause the video before all this it does capture the second set in currentPosition as far as I can see.

Attached the adapted current project in the current state. Just change the input/output files and the startposition (in seconds) in METHOD CaptureVideo() AS VOID and you should be good to go.
VideoCaptureSample.zip
(570.9 KiB) Downloaded 49 times
Dick