Skip to content

feat(preview): generate video previews on an ffmpeg-over-ip server - #65717

Open
szaimen wants to merge 4 commits into
masterfrom
feat/ffmpeg-preview-service
Open

szaimen wants to merge 4 commits into
masterfrom
feat/ffmpeg-preview-service

Conversation

@szaimen

@szaimen szaimen commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Add the OC\Preview\MovieRemote provider which runs ffprobe and ffmpeg on an ffmpeg-over-ip server (https://github.com/steelbrain/ffmpeg-over-ip), similar to the Imaginary provider for images. It is configured with preview_ffmpeg_url and preview_ffmpeg_key; neither ffmpeg nor the ffmpeg-over-ip client is needed on the Nextcloud server.

OC\Preview\FFmpegOverIpClient implements the client side of the protocol in PHP. The server tunnels all file access of the remote process back over the connection, so the video is streamed from any storage, including S3 and external storages. Only the video itself can be opened, read-only. Streams that cannot seek are copied to a temporary stream first.



Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@szaimen szaimen added this to the Nextcloud 36 milestone Oct 20, 2026
@szaimen szaimen added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Oct 20, 2026
@szaimen
szaimen marked this pull request as ready for review October 20, 2026 10:23
@szaimen
szaimen requested a review from a team as a code owner October 20, 2026 10:23
@szaimen
szaimen requested review from Altahrim, CarlSchwan, SystemKeeper, come-nc, icewind1991, provokateurin, sorbaugh and susnux and removed request for a team October 20, 2026 10:23
szaimen added a commit to nextcloud/all-in-one that referenced this pull request Oct 20, 2026
Ship the ffmpeg preview service from nextcloud/server#65717 inside the
imaginary container and configure the OC\Preview\MovieRemote provider
automatically when imaginary is enabled. The service script gets synced
from server via the imaginary-update workflow. Uploaded videos are
buffered in a dedicated volume instead of a tmpfs to not use up RAM.

ffmpeg is removed from the Nextcloud container as video previews are now
generated by the imaginary container.

Assisted-by: ClaudeCode:claude-opus-5-5
Signed-off-by: Simon L. <szaimen@e.mail.de>
szaimen added a commit to nextcloud/documentation that referenced this pull request Oct 20, 2026
Relates to nextcloud/server#65717 and nextcloud/all-in-one#8865

Assisted-by: Claude Code:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
szaimen added a commit to nextcloud/documentation that referenced this pull request Oct 20, 2026
Relates to nextcloud/server#65717 and nextcloud/all-in-one#8865

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
szaimen added a commit to nextcloud/documentation that referenced this pull request Oct 20, 2026
Relates to nextcloud/server#65717 and nextcloud/all-in-one#8865

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Simon L. <szaimen@e.mail.de>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
Comment thread build/ffmpeg-preview-service/server.py Resolved
Comment thread build/ffmpeg-preview-service/Dockerfile Resolved

@susnux susnux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think docker containers for deployment belong into the server repository.
And especially not into the build folder.

This would belong to either some dedicated ffmpeg preview app or at least the container should be handled somewhere else like docker-ci or even a new repository.

@SystemKeeper

Copy link
Copy Markdown
Contributor

I am also a bit twisted on having this in the server repository tbh. But what I am wondering, isn’t there something prebuilt like this that we could use?

@szaimen szaimen added 2. developing Work in progress and removed 3. to review Waiting for reviews labels Nov 2, 2026
@susnux

susnux commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

isn’t there something prebuilt like this that we could use?

maybe https://github.com/steelbrain/ffmpeg-over-ip

@szaimen szaimen left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WIll try to make the implementation compatible with https://github.com/steelbrain/ffmpeg-over-ip going forward :)

@szaimen
szaimen marked this pull request as draft November 2, 2026 14:56
Add the OC\Preview\MovieRemote provider which runs ffprobe and ffmpeg on an
ffmpeg-over-ip server (https://github.com/steelbrain/ffmpeg-over-ip),
similar to the Imaginary provider for images. It is configured with
preview_ffmpeg_url and preview_ffmpeg_key; neither ffmpeg nor the
ffmpeg-over-ip client is needed on the Nextcloud server.

OC\Preview\FFmpegOverIpClient implements the client side of the protocol in
PHP. The server tunnels all file access of the remote process back over the
connection, so the video is streamed from any storage, including S3 and
external storages. Only the video itself can be opened, read-only. Streams
that cannot seek are copied to a temporary stream first.

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
@szaimen
szaimen force-pushed the feat/ffmpeg-preview-service branch from 2ba7e52 to 6ca6cbe Compare November 3, 2026 15:14
@szaimen szaimen changed the title feat(preview): generate video previews with an external ffmpeg service feat(preview): generate video previews on an ffmpeg-over-ip server Nov 3, 2026
szaimen added a commit to nextcloud/all-in-one that referenced this pull request Nov 3, 2026
Add the nextcloud-aio-ffmpeg container which runs the ffmpeg-over-ip server
(https://github.com/steelbrain/ffmpeg-over-ip) and configure the
OC\Preview\MovieRemote provider from nextcloud/server#65717 automatically when
it is enabled. The container is enabled by default and can be disabled in the
AIO interface. The ffmpeg-over-ip release gets pinned by its checksums and is
kept up-to-date within the major version by the ffmpeg-over-ip-update workflow.

ffmpeg stays in the Nextcloud container so that video previews keep working
when the container is disabled.

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
szaimen added a commit to nextcloud/documentation that referenced this pull request Nov 3, 2026
Relates to nextcloud/server#65717 and nextcloud/all-in-one#8865

Assisted-by: Claude Code:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
@szaimen szaimen added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Nov 3, 2026
@szaimen
szaimen marked this pull request as ready for review November 3, 2026 15:43
@szaimen

szaimen commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

isn’t there something prebuilt like this that we could use?

maybe https://github.com/steelbrain/ffmpeg-over-ip

done :)

@susnux susnux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better now :)

Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
- Only download the first 10 MB of videos on storages that cannot seek,
  using ProviderV2::getLocalFile() like the Movie provider, and send the
  real size of that file
- Allow tls:// addresses with peer verification and reject http(s) urls
  with a clear error
- Apply one configurable deadline (preview_ffmpeg_timeout) to all runs of
  a preview instead of 120 seconds per run
- Fall back to non-HDR previews if ffprobe fails
- Reject seeks that would overflow the file offset
- Report the provider as unavailable without preview_ffmpeg_address
- Rename preview_ffmpeg_url to preview_ffmpeg_address, as it is no url
- Share the timestamps and ffmpeg arguments with the Movie provider

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
@szaimen

szaimen commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

Better now :)

Addressed all your comments. Please check again :)

@szaimen
szaimen requested a review from susnux November 4, 2026 13:59
Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>

@susnux susnux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some findings from a deeper review pass, roughly ordered by severity. Most of them were reproduced against a fake ffmpeg-over-ip server, the real SeekableHttpStream/Icewind wrappers and real ffmpeg 8.1.3.

AI-assisted review (Claude Code), findings checked by reproduction.

Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
Comment thread lib/private/PreviewManager.php Resolved
Comment thread lib/private/Preview/MovieRemote.php Resolved
@szaimen

szaimen commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Some findings from a deeper review pass, roughly ordered by severity. Most of them were reproduced against a fake ffmpeg-over-ip server, the real SeekableHttpStream/Icewind wrappers and real ffmpeg 8.1.3.

Should be adressed now. Please check again :)

@szaimen
szaimen requested a review from susnux November 5, 2026 08:31
…client

- Open the video on the storage, so it is not locked while the server works
- Take the size from the opened stream instead of the filecache
- Limit the data the server may read of videos on non-local storages to
  20 MB, like the Movie provider
- Track the stream position after failed seeks and report short reads as
  I/O errors instead of end of file
- Send a cancel message when a run is aborted
- Enforce the deadline while writing with non-blocking writes
- Catch all errors and give up after the first failed connection
- Report the reason of TLS errors, verify IPv6 literals and document the
  certificate bundle that is used
- Register MovieRemote before Movie and log if no address is configured
- Use the default timeout for values below 1

Assisted-by: ClaudeCode:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
@szaimen
szaimen force-pushed the feat/ffmpeg-preview-service branch from 8a9086e to d18936a Compare November 5, 2026 09:19
@szaimen

This comment was marked as resolved.

szaimen added a commit to nextcloud/documentation that referenced this pull request Nov 5, 2026
Follow nextcloud/server#65717: rename preview_ffmpeg_url to
preview_ffmpeg_address, document tls:// and unix: addresses, the
preview_ffmpeg_timeout option and the read limits on non-local storages,
and that MovieRemote is tried before Movie when both are enabled.

Assisted-by: Claude Code:claude-opus-5-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
@szaimen

szaimen commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

@CarlSchwan would you mind having another look at this? :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants