Skip Navigation
Issue Tracker @lemm.ee issue_tracking_bot @lemm.ee
BOT

[BE] Better video URL resolution and embedding #3633

github.com Better video URL resolution and embedding · Issue #3633 · LemmyNet/lemmy

Requirements Is this a feature request? For questions or discussions use https://lemmy.ml/c/lemmy_support Did you check to see if this issue already exists? Is this only a feature request? Do not p...

Better video URL resolution and embedding · Issue #3633 · LemmyNet/lemmy

Requirements

  • [X] Is this a feature request? For questions or discussions use https://lemmy.ml/c/lemmy_support
  • [X] Did you check to see if this issue already exists?
  • [X] Is this only a feature request? Do not put multiple feature requests in one issue.
  • [X] Is this a backend issue? Use the lemmy-ui repo for UI / frontend issues.

Is your proposal related to a problem?

Many videos from external sites fail to properly embed on Lemmy clients. Video detection from a URL is based on opengraph tags (specifically og:video), which a lot of sites intentionally don't send, and should be made more intelligent to ensure better content sharing. This is a major sore point for Lemmy at the moment.

Describe the solution you'd like.

To facilitate better video embedding, the fetch_site_metadata function needs to be improved - this way, no UI changes will be required. One easy and cheap way to do this might be to use something like yt-dlp, which can extract direct video URLs from indirect URLs. There are Rust wrappers available for the library.

For example, consider the imgur URL https://imgur.com/gallery/hOPRxdR. From this, yt-dlp is able to extract the direct MP4:

~ ❯ yt-dlp https://imgur.com/gallery/hOPRxdR -g
https://i.imgur.com/txMlHj7.mp4

This process should fail fast. If any error is encountered, simply ditch the approach and fall back to opengraph.

Considerations

  1. This can be too aggressive: for example, YouTube and v.reddit links can be resolved, but they are m3u8 streams that can't be played by the UI in a <video> tag. Only three formats are supported: mp4, webm, and ogg. This can be tuned in the command:
    ~ ❯ yt-dlp https://imgur.com/gallery/hOPRxdR -g -f 'best[ext=webm]/best[ext=mp4]/best[ext=ogg]'
    https://i.imgur.com/txMlHj7.mp4
    
  2. Error handling is required in case a URL can't be selected:
    ~ ❯ yt-dlp https://v.redd.it/s2426qje27cb1 -g -f 'best[ext=webm]/best[ext=mp4]/best[ext=ogg]'
    ERROR: [Reddit] s2426qje27cb1: Requested format is not available. Use --list-formats for a list of available formats 
    
    This is a non-zero exit code, so the normal fail-fast behavior might be enough.

Describe alternatives you've considered.

I considered using yt-dlp to also do the downloading of a video to pictrs, but that seems like unnecessary storage use. I'm sure there are alternative solutions out there.

Additional context

Sample Rust code (I am not a Rust programmer so don't judge)

fn run_ytdl(input: &str) -> Result<YoutubeDlOutput, youtube_dl::Error> {
    YoutubeDl::new(input)
        .download(false)
        .format("best[ext=webm]/best[ext=mp4]/best[ext=ogg]")
        .socket_timeout("10")
        .run()
}

fn extract_direct_url(input: &str) -> Option<String> {
    let output = run_ytdl(input).ok()?;

    match output {
        YoutubeDlOutput::Playlist(playlist) => playlist.entries?.get(0)?.clone().url,
        YoutubeDlOutput::SingleVideo(video) => video.url
    }
}
1