fix: improve video processing fps assignment logic
Author: Xqle
Pull request: yes

# What does this PR do?

#### 1. Improve `fps` handling in `Qwen2_5_VLProcessor.__call__()`
- Previously, the `__call__()` function always defaulted to `fps=2`, regardless of the input video.

- Now, when fps is not explicitly provided and cannot be read from the video metadata, it falls back to 24 by default. Otherwise, the provided or metadata fps is used. It follows a priority order:
  ```python
  kwargs["fps"] → video_metadata["fps"] → 24 (default)
  ```
  The default value 24 is chosen as it represents a common frame rate for most videos.
- This prevents potential errors in `second_per_grid_ts` calculation when the actual video frame rate differs from the assumed default.
#### 2. More robust `do_sample_frames` behavior
- If `fps` is manually provided but `do_sample_frames` is not specified, `do_sample_frames` will now be automatically set to True.
- This avoids cases where custom fps is ignored due to missing sampling flag.


## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [x] Did you read the [contributor guideline](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#create-a-pull-request),
      Pull Request section?
- [ ] Was this discussed/approved via a Github issue or the [forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [x] Did you make sure to update the documentation with your changes? Here are the
      [documentation guidelines](https://github.com/huggingface/transformers/tree/main/docs), and
      [here are tips on formatting docstrings](https://github.com/huggingface/transformers/tree/main/docs#writing-source-documentation).
- [ ] Did you write any new necessary tests?


## Who can review?

@zucchini-nlp

<!-- Your PR will be replied to more quickly if you can figure out the right person to tag with @

 If you know how to use git blame, that is the easiest way, otherwise, here is a rough guide of **who to tag**.
 Please tag fewer than 3 people.

Models:

- text models: @ArthurZucker @Cyrilvallez
- vision models: @yonigozlan @molbap
- audio models: @eustlb @ebezzam @vasqu
- multimodal models: @zucchini-nlp
- graph models: @clefourrier

Library:

- generate: @zucchini-nlp (visual-language models) or @gante (all others)
- continuous batching: @remi-or @ArthurZucker @McPatate
- pipelines: @Rocketknight1
- tokenizers: @ArthurZucker and @itazap
- trainer: @SunMarc
- attention: @vasqu @ArthurZucker @CyrilVallez
- model loading (from pretrained, etc): @CyrilVallez
- distributed: @3outeille @ArthurZucker
- CIs: @ydshieh

Integrations:

- ray/raytune: @richardliaw, @amogkam
- Big Model Inference: @SunMarc
- quantization: @SunMarc @MekkCyber
- kernels: @MekkCyber @drbh
- peft: @BenjaminBossan @githubnemo

Devices/Backends:

- AMD ROCm: @ivarflakstad
- Intel XPU: @IlyasMoutawwakil
- Ascend NPU: @ivarflakstad 

Documentation: @stevhliu

Research projects are not maintained and should be taken as is.

 -->


Comments:
cc @molbap @yonigozlan for processors

@zucchini-nlp

Thanks for the review. But I think the `fps` should align with the fps of **video after video processing**, no matter the video is sampled during video processing or not.
Please see my reply for your comments above.

@zucchini-nlp I've added `sampled_fps` to the metadata as discussed. If this implementation looks good to you, I can also update the other models that use FPS in a similar way. From what I’ve checked, only `qwen3_omni_moe` and `qwen2_5_omni` would need similar changes.

Also, I noticed a potential inconsistency regarding the previously discussed `do_sample_frames` flag. 
- When calling `processor.apply_chat_template(..., tokenize=True, fps=1)`, `do_sample_frames` is automatically set to True (see [code](https://github.com/huggingface/transformers/blob/8012f80f722044fd0dda45b4034f89fffc2ff344/src/transformers/processing_utils.py#L1675C1-L1680C50) in `processor_utils.py`).
- However, if we call `processor.apply_chat_template(..., tokenize=False)` and then use `processor(..., fps=1)` manually for processing, `do_sample_frames` remains unset. So the video will not be sampled and there’s no warning or error about it.

I understand your previous concern that adding this logic inside the processor might require updating every model’s processor implementation, which could be non-trivial. Maybe we could move the flag assignment from `processor_utils.apply_chat_template` to `video_processing_utils.preprocess`?

If that sounds reasonable to you, I can open a separate PR to address this specifically.

> Also, I noticed a potential inconsistency regarding the previously discussed do_sample_frames flag.

ah yeah, we had to do the automatic switch trick for BC. Prev we didn't have a dedicated video processor and thus no flag to control the sampling behavior. Sampling was done only when applying chat template by helper functions. So we had to keep it and always same frames when the processor is called via `apply_chat_template`

Though when simply calling, I still think it should not be automatically changing. For all new models it is set to `True` anyway so it will be sampling by default. For old model we have the flag set to `False` (again for BC) and will require users to toggle it if they want sampling

**[For maintainers]** Suggested jobs to run (before merge)

run-slow: qwen2_5_vl

The docs for this PR live [here](https://moon-ci-docs.huggingface.co/docs/transformers/pr_42009). All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.