LingQ Addon: AI Tools & Custom Layouts for an Enhanced Learning Experience

LingQ Addon

A userscript for Tampermonkey/GreaseMonkey that significantly enhances the LingQ language learning experience.

It offers customizable layouts, appearance settings, vocabulary downloading tools, an AI-powered chat widget, AI-based TTS, and workflow improvements, all aimed at streamlining your study process.

Reader Layout


Course Page


Features

  • Customizable Layouts:
    • Video layout: Displays the video below with the text above.
    • Video 2 layout: Displays the video on the right side, with the text to the left. Optimized for wide screens.
    • Audio layout: Optimized for lessons with audio.
    • Off layout: Disables layout changes and focuses on the sentence mode. Provides a movable, resizable video.
  • Appearance Customization:
    • Adjustable font size and line height for improved readability.
    • Dark and Light color themes, with customizable color palette, including the background color for known words.
  • Vocabulary Downloading:
    • Download known and unknown words and phrases from the LingQ interface in CSV format.
  • Workflow Enhancements:
    • Keyboard controls for common tasks such as marking words as known, enabling/disabling full screen for video, moving video time, or copying selected vocab.
    • Optional automatic lesson completion upon audio/video completion.
    • Improved sentence focus ensures sentence being played is automatically moved to the center of the screen.
    • Reset course to first position button.
    • Known words indicator on the library page with percentage detail.
    • Default course sorting option.
  • Chat Widget:
    • An AI-powered chat widget for interacting with the lesson content.
    • An AI-powered flashcard generation.
    • An AI-based TTS model that substitutes original one.
  • Flashcard Management:
    • Create flashcards with a single click based on AI response.
  • Enhanced YouTube player
    • Turns on caption default.
    • Disables the player controller.
    • Adds a video progress indicator synced with the audio player’s progress.
    • Remove the more videos pop-up and youtube logo in the player, so you can read the subtitle while the video is paused.
  • Print a Lesson with Highlighting and the Vocabulary List
  • Generate a Lesson Audio with AI-based TTS

Installation

Desktop

  1. Install a userscript manager like Tampermonkey or GreaseMonkey.
  2. Install the script from Project page.
  3. Visit LingQ, and the addon features will be active on reader pages.
  4. If you want to use AI features (Chat, TTS), you need to make an API key. Refer to this tutorial video: Get OpenAI GPT API, Get Google Gemini API.

Android

  1. Install Firefox app.
  2. Install Tampermonkey within the browser.
  3. Install the script from Project page.
  4. Visit LingQ, and the addon features will be active on reader pages. If it doesn’t work, refresh the browser.
  5. If you want to use AI features (Chat, TTS), you need to make an API key. Refer to this tutorial video: Get OpenAI GPT API, Get Google Gemini API.

Supabase DB (Optional)

To enable the flashcard feature, you need to create your own Supabase project and connect it with the add-on.

  1. Create a Supabase Project
    Visit Supabase and sign up (or log in).
    Click New Project, choose a name and region, then wait until the database is ready.

  2. Run the Provided SQL
    Open your Project Dashboard > SQL Editor, and paste the provided SQL schema (from this repository).


     CREATE TABLE public.word_data (
         idx SERIAL PRIMARY KEY,
         language text,
         original_word text,
         context text,
         word text,
         pronunciation text,
         meaning text,
         explanation text,
         example_sentence text,
         example_translation text,
         flashcard boolean DEFAULT false,
         created_at timestamptz DEFAULT now()
     );
    

    Click Run to initialize your database structure.
    You should now see a new table named word_data inside your project.

  3. Get the URL and Key
    Go to Project Settings > Data API, and copy the Project URL.



    Then go to Project Settings > API keys, and copy the Publishable key.

  4. Enter the Keys in the Add-on Settings
    Paste your Project URL and Publishable Key into the corresponding fields in the LingQ Addon’s :gear: Settings.
    After saving, you can make flashcards from AI-generated word explanation in a single click.

Usage

Once installed, an “:gear:” (settings), “:floppy_disk:” (download words) and a “:check_mark:” (complete lesson) will be added to the main navigation bar of LingQ when on a lesson page.

Settings


Click the “:gear:” icon to open the settings popup. From there, you can adjust:

  • Layout style: Select preset reader layouts.
  • Color Mode: Select light or dark color mode and customize colors, including font, LingQ background and border, and underlining.
  • Keyboard Shortcuts: Assign new shortcuts for actions.
  • Chat widget: Select LLM Model.
  • AI-TTS: Select TTS voice.

Chat Widget (Word / Sentence)




The add-on includes an AI-powered chat widget designed to enhance your learning experience.
It analyzes the selected text, provides detailed explanations, and lets you interact with the results through convenient tools.

  • Display: When you select a word or sentence, the AI automatically generates an analysis containing pronunciation, meaning, and example sentences.
  • Flashcard View: Clicking on the word title opens your saved flashcards for that word, allowing you to easily review existing ones.
  • Quick Copy: Clicking on a meaning or example sentence copies it directly to your clipboard.
  • Action Buttons:
    • Copy – Copy the entire generated content (definition + examples).
    • Read with TTS – Play the pronunciation using the AI-based voice.
    • Make a Flashcard – Save the current word and explanation to your Supabase database.
    • Regenerate – Re-run the AI request to generate a new explanation or alternative examples.

Downloading Words


Click the “:floppy_disk:” icon to export LingQs, after clicking a popup will open. Use the buttons to download the following:

  • Download Unknown LingQs: Exports LingQs (words + phrases) with statuses 1, 2, 3, and 4 as a CSV file.
  • Download Unknown LingQ Words: Exports words with status 1, 2, 3, and 4
  • Download Unknown LingQ Phrases: Exports phrases with status 1, 2, 3, and 4
  • Download Known LingQs: Exports known LingQs (words + phrases) as a CSV file.
  • Download Known Words: Exports known words as a CSV file.

Reset Course Position


Library courses will have an option to reset lessons to their first position.

Known Words Indicator


Library Lessons are enhanced with an indicator for known words.

Print a Lesson with Highlighting and the Vocabulary List


Generate a Lesson Audio with AI-based TTS


Flashcard Manager


Click the “:memo:” button to open the Flashcard Manager.
Here, you can view, edit, and manage all flashcards stored.


You can import the CSV into Anki using a matching card template.
Follow the steps below to install and use the Anki template:

  1. Download and open the provided LingQ Flashcard Deck.apkg file.
    This will automatically add the “LingQ Flashcard” note type to your Anki collection.
  2. In Anki, go to File → Import, and select the exported CSV file.
  3. When the Import dialog appears, set the following options:

    • Allow HTML in fields: Enabled
    • Note Type: LingQ Flashcard
    • Field mapping: Verify that columns align correctly with each field .

Download Script


If it was helpful to you, you can
Buy Me A Coffee

13 Likes

I made some adjustments to see a large-sized video with its script without clicking the page flip button.

Adjust the value of variables to fit your resolution or env.

Old Code
// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @version      1.3
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 460px; /*video height*/
    
    --font_size: 1.1rem; /*reader font size*/
    --font_color: #e0e0e0; /*font color*/
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle (q key)
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (w key)
    if (event.key === 'w' || event.key === 'W') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (e key)
    if (event.key === 'e' || event.key === 'E') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 500);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
})();

You can adjust video size and layout by changing “–height_big” variable’s value only, others are automatically adjusted.

If it’s useful, plz hit the like button below.


  • You need to change the background color to dark manually or change the color settings.
  • If the video size is small, you need to expand the video window by pressing Q key.
6 Likes

Any way to change the punctuation color as well? The white really stands out if the font color is set to gray.

Change

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

to

  .reader-container p .sentence-item, .reader-container p .sentence {
    color: var(--font_color) !important;
  }

Now it works.


Before


After

1 Like

Yes, that works, thank you.

1 Like

New Feature:

  • Now the sentence playing is located at the center of the screen. You don’t need to scrol acording to the playing video.

If you don’t want the sentence is fixed on the exact center use nearest instead of center in this part of the code playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
It always locates the sentence inside a screen but not center.

Old Code
// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.4
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 470px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w' || event.key === 'W') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e' || event.key === 'E') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r' || event.key === 'R') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
    }
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();

New hotkeys

  • Move the cursor to the reference input (`): it directly moves the keyboard cursor to the text field in the widget.
  • Open Dictionary (d or f): it works when multiple words are selected
  • Open Translator (t): it works when multiple words are selected
  • Copy selected text (c): copy selected text in a clipboard (I use it when using LLM)

Of course, you can change the hotkeys in your favor.


The Open Dictionary key clicks the first dictionary and the Open Translator selects the last. So you need to set them properly



You can change the order of the dicts here.


Old Code
// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.5
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 470px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w') {
      const backward_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (backward_btn) {
        backward_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e') {
      const forkward_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (forkward_btn) {
        forkward_btn.click();
      }
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
      event.stopPropagation();
    }
    
    // Move cursor to the reference input
    if (event.key === '`') {
      const reference_input = document.querySelector('.reference-input-text');

      if (reference_input) {
          reference_input.focus();
          reference_input.setSelectionRange(reference_input.value.length, reference_input.value.length);
      }
      event.preventDefault();
      event.stopPropagation();  
    }
    
    // Open Dictionary
    if (event.key === 'd' || event.key === 'f') {
      const dict_btn = document.querySelector('.dictionary-resources > a:nth-child(1)');
      if (dict_btn) {
        dict_btn.click();
      }
      event.stopPropagation();
    }
    
    // Open Translator
    if (event.key === 't') {
      const translator_btn = document.querySelector('.dictionary-resources > a:nth-last-child(1)');
      if (translator_btn) {
        translator_btn.click();
      }
      event.stopPropagation();
    }
    
    // Copy selected text
    if (event.key === 'c') {
      const selected_text = document.querySelector('.reference-word');
      if (selected_text) {
        navigator.clipboard.writeText(selected_text.textContent);
      }
      event.stopPropagation();
    }
    
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();

I’ve yet to figure out how to enable this script via tampermonkey. Tampermonkey us enabled, I pasted in the script provided and saved it, that’s now in the extension an turned on, I’ve reloaded, nothing works. I’ve enabled developer mode for TM too. I watched a couple videos, nothing is showing the missing step unfortunatly.

1 Like

I’m not sure what the problem is with it.
This is the process i had and works. Uninstall the extension and follow the procedure.

  1. install Tampermonkey from chrome store
  2. open Extension from the upper navbar and click ‘Create a new script’ button.
  3. Copy and paste the script I provide.
  4. refresh LingQ reader page.

image

It could be the issue with the URL format. Let me know the URL of your reader page. Browser also.

Ok I followed those instructions. This time something change a little but nowhere close to what it shoud look like, and I tried it on a clean account with no other extensions which could possibly interfere. I tried it within firefox too and the same weird / incomplete effect happens.

Here is the url I’m on for reader mode:
image

What it looks like for me:

What I pasted in (beginning and end):


Enabled:


image

image

This is the layout I intended. It seems to work on your PC.
Hit the ‘Q’ key after loading the video to expand the video and fill its area.

If the video size is too large, adjust –height_big variable

If your monitor’s resolution is too low, you might need to change the fontsize and video size to reserve enough space for text.

This is 1920x1080 setup

1 Like

Q Key! Ok that resolved it and then I feel like I dope, I was expecting darkmode to be turned on via the script and I realized I needed to enable that seperatly in LingQ settings. Anyway, all good now, thanks for the help!

Yup. Have a good night or day!

1 Like

How can I change this situation??

Click the Aa button in the upper right corner and select the black background color. If you prefer light mode, change color values in the source code.

This css is for audio lesson users.

Old Code
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 5px);
    --height_big: 10px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 2.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 175px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 1 / 2 / -1 / 2 !important;
}
  
  .main-content {
    grid-template-rows: 45px 1fr !important;
    overflow: hidden;
    grid-area: 1 / 1 / 2 / 1 !important;
    align-items: anchor-center;
}
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }

It hides the annoying “more videos” popup and the YT logo from the mini video player.
You can read subtitles when a video is paused.
Use it together with my LingQ Add-on script.

Before

After

Old Code
// ==UserScript==
// @name         Collapse More-videos
// @description  Automatically collapse More videos popup in YouTube.
// @match        https://www.youtube-nocookie.com/*
// @version      1.5
// ==/UserScript==

(function () {
  "use strict";
  
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;

    // dismiss subtitle background opacity setting key (w)
    if (event.key === 'w') {
    console.log('w');
    event.preventDefault(); 
    event.stopPropagation();
    }
  }, true); 
  
  function clickPlayButton() {
    document.querySelector(".ytp-button.ytp-large-play-button").click();
  }

  function clickCollapseButton() {
    document.querySelector(".ytp-button.ytp-collapse").click();
  }

  function clickSubtitleButton() {
    document.querySelector(".ytp-button.ytp-subtitles-button").click();
  }

  window.addEventListener("load", function () {
    setTimeout(() => {
      clickPlayButton();
      clickCollapseButton();
      clickPlayButton();
    }, 100);
  });

  var style = document.createElement("style");
  style.textContent = `
  div.ytp-pause-overlay{
    visibility: hidden !important;
  }
  a.ytp-watermark{
    visibility: hidden !important;
  }
`;

  document.querySelector("head").appendChild(style);
})();


In the default lingQ interface, the state 4 of the word will hide the yellow prompt, but the yellow prompt will still be displayed under the script, how can I change the target, and the yellow prompt will be hidden when the state 4 is hidden?

I intentionally maintained the border of the known words. If you don’t like it, change the code.

--lingq_border_learned: hsl(43 99% 64% / 0.5);
to
--lingq_border_learned: hsl(43 99% 64% / 0);


Additional Tip

You can open DevTools with F12 key. There, you can change the variables interatively. Use it when you test UI elements.
(The change made here is not saved, so make sure that you change the corresponding script’s values.)

Change Log

v1.6: Now, LingQ uses “youtube.com” player, not “youtube-nocookie.com”. Some code is updated for that change.

Also, now the videos you watch in LingQ show up in YouTube watch history (previously not). In other words, YT algorithm will consider the video played in LingQ.

LingQ automatically play the video, and auto-played video doesn’t counted as a view. So, not appear in YT history page.

Old Code

Script for YouTube Player

// ==UserScript==
// @name         Collapse More-videos
// @description  Automatically collapse More videos popup in YouTube.
// @match        https://www.youtube-nocookie.com/*
// @match        https://www.youtube.com/embed/*
// @version      1.6
// ==/UserScript==

(function () {
  "use strict";
  
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;

    // dismiss subtitle background opacity setting key (w)
    if (event.key === 'w') {
    console.log('w');
    event.preventDefault(); 
    event.stopPropagation();
    }
  }, true); 
  
  function clickPlayButton() {
    document.querySelector(".ytp-button.ytp-large-play-button").click();
  }

  function clickCollapseButton() {
    document.querySelector(".ytp-button.ytp-collapse").click();
  }

  function clickSubtitleButton() {
    document.querySelector(".ytp-button.ytp-subtitles-button").click();
  }

  window.addEventListener("load", function () {
    setTimeout(() => {
      clickPlayButton();
      clickCollapseButton();
      clickPlayButton();
    }, 100);
  });

  var style = document.createElement("style");
  style.textContent = `
  div.ytp-pause-overlay{
    visibility: hidden !important;
  }
  a.ytp-watermark{
    visibility: hidden !important;
  }
`;

  document.querySelector("head").appendChild(style);
})();

Script for LingQ website

// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.6
// ==/UserScript==

(function () {
  "use strict";

  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  //PASTE THE CSS HERE
  `;
  document.querySelector("head").appendChild(style);
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w') {
      const backward_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (backward_btn) {
        backward_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e') {
      const forkward_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (forkward_btn) {
        forkward_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Move cursor to the reference input
    if (event.key === '`') {
      const reference_input = document.querySelector('.reference-input-text');

      if (reference_input) {
          reference_input.focus();
          reference_input.setSelectionRange(reference_input.value.length, reference_input.value.length);
      }
      event.preventDefault();
      event.stopPropagation();  
    }
    
    // Open Dictionary
    if (event.key === 'd' || event.key === 'f') {
      const dict_btn = document.querySelector('.dictionary-resources > a:nth-child(1)');
      if (dict_btn) {
        dict_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Open Translator
    if (event.key === 't') {
      const translator_btn = document.querySelector('.dictionary-resources > a:nth-last-child(1)');
      if (translator_btn) {
        translator_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Copy selected text
    if (event.key === 'c') {
      const selected_text = document.querySelector('.reference-word');
      if (selected_text) {
        navigator.clipboard.writeText(selected_text.textContent);
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('disablekb=1')) {
            // src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();